@@ -35,6 +35,105 @@ void CollectionData::setExpiry(int32_t seconds_until_expiry) {
35
35
m_hasExpiryTime = true ;
36
36
}
37
37
38
+ std::string CollectionData::getSerialized () const {
39
+ std::string serialized;
40
+ if (hasValue ()) {
41
+ serialized.reserve (30 + 10 + getValue ().size ());
42
+ } else {
43
+ serialized.reserve (16 +10 );
44
+ }
45
+
46
+ serialized.assign (" {" );
47
+
48
+ if (hasExpiry ()) {
49
+ serialized.append (" \" __expire_\" :" );
50
+ uint64_t expiryEpochSeconds = std::chrono::duration_cast<std::chrono::seconds>(m_expiryTime.time_since_epoch ()).count ();
51
+ serialized.append (std::to_string (expiryEpochSeconds));
52
+ if (hasValue ()) {
53
+ serialized.append (" ," );
54
+ }
55
+ }
56
+ if (hasValue ()) {
57
+ serialized.append (" \" __value_\" :\" " );
58
+ serialized.append (getValue ());
59
+ serialized.append (" \" " );
60
+ }
61
+
62
+ serialized.append (" }" );
63
+
64
+ return serialized;
65
+ }
66
+
67
+ void CollectionData::setFromSerialized (const char * serializedData, size_t length) {
68
+ const static std::string expiryPrefix (" \" __expire_\" :" );
69
+ const static std::string valuePrefix (" \" __value_\" :\" " );
70
+ m_hasValue = false ;
71
+ m_hasExpiryTime = false ;
72
+
73
+ std::string serializedString (serializedData, length);
74
+ if ((serializedString.find (" {" ) == 0 ) && (serializedString.substr (serializedString.length ()-1 ) == " }" )) {
75
+ size_t currentPos = 1 ;
76
+ uint64_t expiryEpochSeconds = 0 ;
77
+ bool invalidSerializedFormat = false ;
78
+ bool doneParsing = false ;
79
+
80
+ // Extract the expiry time, if it exists
81
+ if (serializedString.find (expiryPrefix, currentPos) == currentPos) {
82
+ currentPos += expiryPrefix.length ();
83
+ std::string expiryDigits = serializedString.substr (currentPos, 10 );
84
+ if (expiryDigits.find_first_not_of (" 0123456789" ) == std::string::npos) {
85
+ expiryEpochSeconds = strtoll (expiryDigits.c_str (), NULL , 10 );
86
+ } else {
87
+ invalidSerializedFormat = true ;
88
+ }
89
+ currentPos += 10 ;
90
+ }
91
+
92
+ if ((!invalidSerializedFormat) && (expiryEpochSeconds > 0 )) {
93
+ if (serializedString.find (" ," , currentPos) == currentPos) {
94
+ currentPos++;
95
+ } else if (currentPos == serializedString.length ()-1 ) {
96
+ doneParsing = true ;
97
+ } else {
98
+ invalidSerializedFormat = true ;
99
+ }
100
+ }
101
+
102
+ if ((!invalidSerializedFormat) && (!doneParsing)) {
103
+ // Extract the value
104
+ if ((serializedString.find (valuePrefix, currentPos) == currentPos)) {
105
+ currentPos += valuePrefix.length ();
106
+ size_t expectedCloseQuotePos = serializedString.length () - 2 ;
107
+ if ((serializedString.substr (expectedCloseQuotePos, 1 ) == " \" " ) && (expectedCloseQuotePos >= currentPos)) {
108
+ m_value = serializedString.substr (currentPos);
109
+ m_value.resize (m_value.length ()-2 );
110
+ m_hasValue = true ;
111
+ } else {
112
+ invalidSerializedFormat = true ;
113
+ }
114
+ } else {
115
+ invalidSerializedFormat = true ;
116
+ }
117
+ }
118
+
119
+ // Set the object's expiry time, if we found one
120
+ if ((!invalidSerializedFormat) && (expiryEpochSeconds > 0 )) {
121
+ std::chrono::seconds expiryDuration (expiryEpochSeconds);
122
+ std::chrono::system_clock::time_point expiryTimePoint (expiryDuration);
123
+ m_expiryTime = expiryTimePoint;
124
+ m_hasExpiryTime = true ;
125
+ }
126
+ if (!invalidSerializedFormat) {
127
+ return ;
128
+ }
129
+ }
130
+
131
+ // this is the residual case; the entire string is a simple value (not JSON-ish encoded)
132
+ // the foreseen case here is lmdb content from prior to the serialization support
133
+ m_value.assign (serializedData, length);
134
+ m_hasValue = true ;
135
+ return ;
136
+ }
38
137
39
138
} // namespace backend
40
139
} // namespace collection
0 commit comments