1 /**
2 	Generic typesafe ID type to abstract away the underlying database.
3 
4 	Copyright: © 2014-2015 RejectedSoftware e.K.
5 	License: Subject to the terms of the General Public License version 3, as written in the included LICENSE.txt file.
6 	Authors: Sönke Ludwig
7 */
8 module userman.id;
9 
10 import vibe.data.bson;
11 import std.uuid;
12 
13 struct ID(KIND)
14 {
15 	import std.conv;
16 
17 	alias Kind = KIND;
18 
19 	private {
20 		union {
21 			long m_long;
22 			BsonObjectID m_bsonObjectID;
23 			UUID m_uuid;
24 		}
25 		IDType m_type;
26 	}
27 
28 	//alias toString this;
29 
30 	this(long id) { this = id; }
31 	this(BsonObjectID id) { this = id; }
32 	this(UUID id) { this = id; }
33 
34 	@property BsonObjectID bsonObjectIDValue() const { assert(m_type == IDType.bsonObjectID); return m_bsonObjectID; }
35 	@property long longValue() const { assert(m_type == IDType.long_); return m_long; }
36 	@property UUID uuidValue() const { assert(m_type == IDType.uuid); return m_uuid; }
37 
38 	void opAssign(long id) @nogc { m_type = IDType.long_; m_long = id; }
39 	void opAssign(BsonObjectID id) @nogc { m_type = IDType.bsonObjectID; m_bsonObjectID = id; }
40 	void opAssign(UUID id) @nogc { m_type = IDType.uuid; m_uuid = id; }
41 	void opAssign(ID id)
42 	@nogc {
43 		final switch (id.m_type) {
44 			case IDType.long_: this = id.m_long; break;
45 			case IDType.bsonObjectID: this = id.m_bsonObjectID; break;
46 			case IDType.uuid: this = id.m_uuid; break;
47 		}
48 	}
49 
50 	static ID fromBson(Bson id) { return ID(id.get!BsonObjectID); }
51 	Bson toBson() const { assert(m_type == IDType.bsonObjectID); return Bson(m_bsonObjectID); }
52 
53 	static ID fromLong(long id) { return ID(id); }
54 	long toLong() const { assert(m_type == IDType.long_); return m_long; }
55 
56 	static ID fromString(string str)
57 	{
58 		if (str.length == 24) return ID(BsonObjectID.fromString(str));
59 		else if (str.length == 36) return ID(UUID(str));
60 		else return ID(str.to!long);
61 	}
62 
63 	string toString()
64 	const {
65 		final switch (m_type) {
66 			case IDType.long_: return m_long.to!string;
67 			case IDType.bsonObjectID: return m_bsonObjectID.toString();
68 			case IDType.uuid: return m_uuid.toString();
69 		}
70 	}
71 }
72 
73 unittest {
74 	assert(serializeToBson(ID!void(BsonObjectID.init)).type == Bson.Type.objectID);
75 }
76 
77 enum IDType {
78 	long_,
79 	bsonObjectID,
80 	uuid
81 }