Skip to content

Commit fbac5e9

Browse files
committed
WIP: add properly cased files
1 parent f5c4c02 commit fbac5e9

File tree

2 files changed

+368
-0
lines changed

2 files changed

+368
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { ChildrenNode } from "./ChildrenNode";
2+
import { LeafNode } from "./LeafNode";
3+
import { NamedNode } from "./Node";
4+
import { forEach, contains } from "../../../utils/obj";
5+
import { assert } from "../../../utils/assert";
6+
import { buildChildSet } from "./childSet";
7+
import { NAME_COMPARATOR, NAME_ONLY_COMPARATOR } from "./comparators";
8+
import { IndexMap } from "./IndexMap";
9+
import { PRIORITY_INDEX, setNodeFromJSON } from "./indexes/PriorityIndex";
10+
11+
const USE_HINZE = true;
12+
13+
/**
14+
* Constructs a snapshot node representing the passed JSON and returns it.
15+
* @param {*} json JSON to create a node for.
16+
* @param {?string|?number=} opt_priority Optional priority to use. This will be ignored if the
17+
* passed JSON contains a .priority property.
18+
* @return {!Node}
19+
*/
20+
export function nodeFromJSON(json, priority?) {
21+
if (json === null) {
22+
return ChildrenNode.EMPTY_NODE;
23+
}
24+
25+
var priority = null;
26+
if (typeof json === 'object' && '.priority' in json) {
27+
priority = json['.priority'];
28+
} else if (typeof priority !== 'undefined') {
29+
priority = priority;
30+
}
31+
assert(
32+
priority === null ||
33+
typeof priority === 'string' ||
34+
typeof priority === 'number' ||
35+
(typeof priority === 'object' && '.sv' in priority),
36+
'Invalid priority type found: ' + (typeof priority)
37+
);
38+
39+
if (typeof json === 'object' && '.value' in json && json['.value'] !== null) {
40+
json = json['.value'];
41+
}
42+
43+
// Valid leaf nodes include non-objects or server-value wrapper objects
44+
if (typeof json !== 'object' || '.sv' in json) {
45+
var jsonLeaf = /** @type {!(string|number|boolean|Object)} */ (json);
46+
return new LeafNode(jsonLeaf, nodeFromJSON(priority));
47+
}
48+
49+
if (!(json instanceof Array) && USE_HINZE) {
50+
var children = [];
51+
var childrenHavePriority = false;
52+
var hinzeJsonObj = /** @type {!Object} */ (json);
53+
forEach(hinzeJsonObj, function(key, child) {
54+
if (typeof key !== 'string' || key.substring(0, 1) !== '.') { // Ignore metadata nodes
55+
var childNode = nodeFromJSON(hinzeJsonObj[key]);
56+
if (!childNode.isEmpty()) {
57+
childrenHavePriority = childrenHavePriority || !childNode.getPriority().isEmpty();
58+
children.push(new NamedNode(key, childNode));
59+
}
60+
}
61+
});
62+
63+
if (children.length == 0) {
64+
return ChildrenNode.EMPTY_NODE;
65+
}
66+
67+
var childSet = /**@type {!SortedMap.<string, !Node>} */ (buildChildSet(
68+
children, NAME_ONLY_COMPARATOR, function(namedNode) { return namedNode.name; },
69+
NAME_COMPARATOR
70+
));
71+
if (childrenHavePriority) {
72+
var sortedChildSet = buildChildSet(children, PRIORITY_INDEX.getCompare());
73+
return new ChildrenNode(childSet, nodeFromJSON(priority),
74+
new IndexMap({'.priority': sortedChildSet}, {'.priority': PRIORITY_INDEX}));
75+
} else {
76+
return new ChildrenNode(childSet, nodeFromJSON(priority),
77+
IndexMap.Default);
78+
}
79+
} else {
80+
var node = ChildrenNode.EMPTY_NODE;
81+
var jsonObj = /** @type {!Object} */ (json);
82+
forEach(jsonObj, function(childData, key) {
83+
if (contains(jsonObj, key)) {
84+
if (key.substring(0, 1) !== '.') { // ignore metadata nodes.
85+
var childNode = nodeFromJSON(childData);
86+
if (childNode.isLeafNode() || !childNode.isEmpty())
87+
node = node.updateImmediateChild(key, childNode);
88+
}
89+
}
90+
});
91+
92+
return node.updatePriority(nodeFromJSON(priority));
93+
}
94+
};
95+
96+
setNodeFromJSON(nodeFromJSON);

src/utils/Sha1.ts

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
import { Hash } from './hash';
2+
3+
/**
4+
* @fileoverview SHA-1 cryptographic hash.
5+
* Variable names follow the notation in FIPS PUB 180-3:
6+
* http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
7+
*
8+
* Usage:
9+
* var sha1 = new sha1();
10+
* sha1.update(bytes);
11+
* var hash = sha1.digest();
12+
*
13+
* Performance:
14+
* Chrome 23: ~400 Mbit/s
15+
* Firefox 16: ~250 Mbit/s
16+
*
17+
*/
18+
19+
/**
20+
* SHA-1 cryptographic hash constructor.
21+
*
22+
* The properties declared here are discussed in the above algorithm document.
23+
* @constructor
24+
* @extends {Hash}
25+
* @final
26+
* @struct
27+
*/
28+
export class Sha1 extends Hash {
29+
/**
30+
* Holds the previous values of accumulated variables a-e in the compress_
31+
* function.
32+
* @type {!Array<number>}
33+
* @private
34+
*/
35+
private chain_: Array<number> = [];
36+
37+
/**
38+
* A buffer holding the partially computed hash result.
39+
* @type {!Array<number>}
40+
* @private
41+
*/
42+
private buf_: Array<number> = [];
43+
44+
/**
45+
* An array of 80 bytes, each a part of the message to be hashed. Referred to
46+
* as the message schedule in the docs.
47+
* @type {!Array<number>}
48+
* @private
49+
*/
50+
private W_: Array<number> = [];
51+
52+
/**
53+
* Contains data needed to pad messages less than 64 bytes.
54+
* @type {!Array<number>}
55+
* @private
56+
*/
57+
private pad_: Array<number> = [];
58+
59+
/**
60+
* @private {number}
61+
*/
62+
private inbuf_: number = 0;
63+
64+
/**
65+
* @private {number}
66+
*/
67+
private total_: number = 0;
68+
69+
constructor() {
70+
super();
71+
72+
this.blockSize = 512 / 8;
73+
74+
this.pad_[0] = 128;
75+
for (var i = 1; i < this.blockSize; ++i) {
76+
this.pad_[i] = 0;
77+
}
78+
79+
this.reset();
80+
}
81+
82+
reset() {
83+
this.chain_[0] = 0x67452301;
84+
this.chain_[1] = 0xefcdab89;
85+
this.chain_[2] = 0x98badcfe;
86+
this.chain_[3] = 0x10325476;
87+
this.chain_[4] = 0xc3d2e1f0;
88+
89+
this.inbuf_ = 0;
90+
this.total_ = 0;
91+
}
92+
93+
94+
/**
95+
* Internal compress helper function.
96+
* @param {!Array<number>|!Uint8Array|string} buf Block to compress.
97+
* @param {number=} opt_offset Offset of the block in the buffer.
98+
* @private
99+
*/
100+
compress_(buf, opt_offset?) {
101+
if (!opt_offset) {
102+
opt_offset = 0;
103+
}
104+
105+
var W = this.W_;
106+
107+
// get 16 big endian words
108+
if (typeof buf === 'string') {
109+
for (var i = 0; i < 16; i++) {
110+
// TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS
111+
// have a bug that turns the post-increment ++ operator into pre-increment
112+
// during JIT compilation. We have code that depends heavily on SHA-1 for
113+
// correctness and which is affected by this bug, so I've removed all uses
114+
// of post-increment ++ in which the result value is used. We can revert
115+
// this change once the Safari bug
116+
// (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and
117+
// most clients have been updated.
118+
W[i] = (buf.charCodeAt(opt_offset) << 24) |
119+
(buf.charCodeAt(opt_offset + 1) << 16) |
120+
(buf.charCodeAt(opt_offset + 2) << 8) |
121+
(buf.charCodeAt(opt_offset + 3));
122+
opt_offset += 4;
123+
}
124+
} else {
125+
for (var i = 0; i < 16; i++) {
126+
W[i] = (buf[opt_offset] << 24) |
127+
(buf[opt_offset + 1] << 16) |
128+
(buf[opt_offset + 2] << 8) |
129+
(buf[opt_offset + 3]);
130+
opt_offset += 4;
131+
}
132+
}
133+
134+
// expand to 80 words
135+
for (var i = 16; i < 80; i++) {
136+
var t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
137+
W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;
138+
}
139+
140+
var a = this.chain_[0];
141+
var b = this.chain_[1];
142+
var c = this.chain_[2];
143+
var d = this.chain_[3];
144+
var e = this.chain_[4];
145+
var f, k;
146+
147+
// TODO(user): Try to unroll this loop to speed up the computation.
148+
for (var i = 0; i < 80; i++) {
149+
if (i < 40) {
150+
if (i < 20) {
151+
f = d ^ (b & (c ^ d));
152+
k = 0x5a827999;
153+
} else {
154+
f = b ^ c ^ d;
155+
k = 0x6ed9eba1;
156+
}
157+
} else {
158+
if (i < 60) {
159+
f = (b & c) | (d & (b | c));
160+
k = 0x8f1bbcdc;
161+
} else {
162+
f = b ^ c ^ d;
163+
k = 0xca62c1d6;
164+
}
165+
}
166+
167+
var t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;
168+
e = d;
169+
d = c;
170+
c = ((b << 30) | (b >>> 2)) & 0xffffffff;
171+
b = a;
172+
a = t;
173+
}
174+
175+
this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;
176+
this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;
177+
this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;
178+
this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;
179+
this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;
180+
}
181+
182+
update(bytes, opt_length?) {
183+
// TODO(johnlenz): tighten the function signature and remove this check
184+
if (bytes == null) {
185+
return;
186+
}
187+
188+
if (opt_length === 'undefined') {
189+
opt_length = bytes.length;
190+
}
191+
192+
var lengthMinusBlock = opt_length - this.blockSize;
193+
var n = 0;
194+
// Using local instead of member variables gives ~5% speedup on Firefox 16.
195+
var buf = this.buf_;
196+
var inbuf = this.inbuf_;
197+
198+
// The outer while loop should execute at most twice.
199+
while (n < opt_length) {
200+
// When we have no data in the block to top up, we can directly process the
201+
// input buffer (assuming it contains sufficient data). This gives ~25%
202+
// speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that
203+
// the data is provided in large chunks (or in multiples of 64 bytes).
204+
if (inbuf == 0) {
205+
while (n <= lengthMinusBlock) {
206+
this.compress_(bytes, n);
207+
n += this.blockSize;
208+
}
209+
}
210+
211+
if (typeof bytes === 'string') {
212+
while (n < opt_length) {
213+
buf[inbuf] = bytes.charCodeAt(n);
214+
++inbuf;
215+
++n;
216+
if (inbuf == this.blockSize) {
217+
this.compress_(buf);
218+
inbuf = 0;
219+
// Jump to the outer loop so we use the full-block optimization.
220+
break;
221+
}
222+
}
223+
} else {
224+
while (n < opt_length) {
225+
buf[inbuf] = bytes[n];
226+
++inbuf;
227+
++n;
228+
if (inbuf == this.blockSize) {
229+
this.compress_(buf);
230+
inbuf = 0;
231+
// Jump to the outer loop so we use the full-block optimization.
232+
break;
233+
}
234+
}
235+
}
236+
}
237+
238+
this.inbuf_ = inbuf;
239+
this.total_ += opt_length;
240+
}
241+
242+
243+
/** @override */
244+
digest() {
245+
var digest = [];
246+
var totalBits = this.total_ * 8;
247+
248+
// Add pad 0x80 0x00*.
249+
if (this.inbuf_ < 56) {
250+
this.update(this.pad_, 56 - this.inbuf_);
251+
} else {
252+
this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));
253+
}
254+
255+
// Add # bits.
256+
for (var i = this.blockSize - 1; i >= 56; i--) {
257+
this.buf_[i] = totalBits & 255;
258+
totalBits /= 256; // Don't use bit-shifting here!
259+
}
260+
261+
this.compress_(this.buf_);
262+
263+
var n = 0;
264+
for (var i = 0; i < 5; i++) {
265+
for (var j = 24; j >= 0; j -= 8) {
266+
digest[n] = (this.chain_[i] >> j) & 255;
267+
++n;
268+
}
269+
}
270+
return digest;
271+
}
272+
}

0 commit comments

Comments
 (0)