1 |
|
2 | var MACHINE_ID = Math.floor(Math.random() * 0xFFFFFF);
|
3 | var index = ObjectID.index = parseInt(Math.random() * 0xFFFFFF, 10);
|
4 | var pid = (typeof process === 'undefined' || typeof process.pid !== 'number' ? Math.floor(Math.random() * 100000) : process.pid) % 0xFFFF;
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | var isBuffer = function (obj) {
|
14 | return !!(
|
15 | obj != null &&
|
16 | obj.constructor &&
|
17 | typeof obj.constructor.isBuffer === 'function' &&
|
18 | obj.constructor.isBuffer(obj)
|
19 | )
|
20 | };
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | function ObjectID(arg) {
|
30 | if(!(this instanceof ObjectID)) return new ObjectID(arg);
|
31 | if(arg && ((arg instanceof ObjectID) || arg._bsontype==="ObjectID"))
|
32 | return arg;
|
33 |
|
34 | var buf;
|
35 |
|
36 | if(isBuffer(arg) || (Array.isArray(arg) && arg.length===12)) {
|
37 | buf = Array.prototype.slice.call(arg);
|
38 | }
|
39 | else if(typeof arg === "string") {
|
40 | if(arg.length!==12 && !ObjectID.isValid(arg))
|
41 | throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");
|
42 |
|
43 | buf = buffer(arg);
|
44 | }
|
45 | else if(/number|undefined/.test(typeof arg)) {
|
46 | buf = buffer(generate(arg));
|
47 | }
|
48 |
|
49 | Object.defineProperty(this, "id", {
|
50 | enumerable: true,
|
51 | get: function() { return String.fromCharCode.apply(this, buf); }
|
52 | });
|
53 | Object.defineProperty(this, "str", {
|
54 | get: function() { return buf.map(hex.bind(this, 2)).join(''); }
|
55 | });
|
56 | }
|
57 | module.exports = ObjectID;
|
58 | ObjectID.generate = generate;
|
59 | ObjectID.default = ObjectID;
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | ObjectID.createFromTime = function(time){
|
69 | time = parseInt(time, 10) % 0xFFFFFFFF;
|
70 | return new ObjectID(hex(8,time)+"0000000000000000");
|
71 | };
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | ObjectID.createFromHexString = function(hexString) {
|
81 | if(!ObjectID.isValid(hexString))
|
82 | throw new Error("Invalid ObjectID hex string");
|
83 |
|
84 | return new ObjectID(hexString);
|
85 | };
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | ObjectID.isValid = function(objectid) {
|
98 | if(!objectid || (typeof objectid !== 'string' && (typeof objectid !== 'object' || Array.isArray(objectid) || typeof objectid.toString !== 'function'))) return false;
|
99 |
|
100 |
|
101 |
|
102 | return /^[0-9A-F]{24}$/i.test(objectid.toString());
|
103 | };
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | ObjectID.setMachineID = function(arg) {
|
113 | var machineID;
|
114 |
|
115 | if(typeof arg === "string") {
|
116 |
|
117 | machineID = parseInt(arg, 16);
|
118 |
|
119 |
|
120 | if(isNaN(machineID)) {
|
121 | arg = ('000000' + arg).substr(-7,6);
|
122 |
|
123 | machineID = "";
|
124 | for(var i = 0;i<6; i++) {
|
125 | machineID += (arg.charCodeAt(i));
|
126 | }
|
127 | }
|
128 | }
|
129 | else if(/number|undefined/.test(typeof arg)) {
|
130 | machineID = arg | 0;
|
131 | }
|
132 |
|
133 | MACHINE_ID = (machineID & 0xFFFFFF);
|
134 | }
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 | ObjectID.getMachineID = function() {
|
143 | return MACHINE_ID;
|
144 | }
|
145 |
|
146 | ObjectID.prototype = {
|
147 | _bsontype: 'ObjectID',
|
148 | constructor: ObjectID,
|
149 |
|
150 | /**
|
151 | * Return the ObjectID id as a 24 byte hex string representation
|
152 | *
|
153 | * @return {String} return the 24 byte hex string representation.
|
154 | * @api public
|
155 | */
|
156 | toHexString: function() {
|
157 | return this.str;
|
158 | },
|
159 |
|
160 | |
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 | equals: function (other){
|
168 | return !!other && this.str === other.toString();
|
169 | },
|
170 |
|
171 | |
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | getTimestamp: function(){
|
178 | return new Date(parseInt(this.str.substr(0,8), 16) * 1000);
|
179 | }
|
180 | };
|
181 |
|
182 | function next() {
|
183 | return index = (index+1) % 0xFFFFFF;
|
184 | }
|
185 |
|
186 | function generate(time) {
|
187 | if (typeof time !== 'number')
|
188 | time = Date.now()/1000;
|
189 |
|
190 |
|
191 | time = parseInt(time, 10) % 0xFFFFFFFF;
|
192 |
|
193 |
|
194 | return hex(8,time) + hex(6,MACHINE_ID) + hex(4,pid) + hex(6,next());
|
195 | }
|
196 |
|
197 | function hex(length, n) {
|
198 | n = n.toString(16);
|
199 | return (n.length===length)? n : "00000000".substring(n.length, length) + n;
|
200 | }
|
201 |
|
202 | function buffer(str) {
|
203 | var i=0,out=[];
|
204 |
|
205 | if(str.length===24)
|
206 | for(;i<24; out.push(parseInt(str[i]+str[i+1], 16)),i+=2);
|
207 |
|
208 | else if(str.length===12)
|
209 | for(;i<12; out.push(str.charCodeAt(i)),i++);
|
210 |
|
211 | return out;
|
212 | }
|
213 |
|
214 | var inspect = (Symbol && Symbol.for('nodejs.util.inspect.custom')) || 'inspect';
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 | ObjectID.prototype[inspect] = function() { return "ObjectID("+this+")" };
|
223 | ObjectID.prototype.toJSON = ObjectID.prototype.toHexString;
|
224 | ObjectID.prototype.toString = ObjectID.prototype.toHexString;
|