public void PackTo(ref TupleWriter writer) { for (int i = 0; i < m_count; i++) { TuplePackers.SerializeObjectTo(ref writer, m_items[i + m_offset]); } }
public void PackKey(ref SliceWriter writer, IFdbTuple items) { var tw = new TupleWriter(writer); FdbTuple.Pack(ref tw, items); writer = tw.Output; }
/// <summary>Writes a char array encoded in UTF-8</summary> internal static unsafe void WriteChars(ref TupleWriter writer, char[] value, int offset, int count) { Contract.Requires(offset >= 0 && count >= 0); if (count == 0) { if (value == null) { // "00" WriteNil(ref writer); } else { // "02 00" writer.Output.WriteByte2(FdbTupleTypes.Utf8, 0x00); } } else { fixed(char *chars = value) { if (!TryWriteUnescapedUtf8String(ref writer, chars + offset, count)) { // the string contains \0 chars, we need to do it the hard way WriteNulEscapedBytes(ref writer, FdbTupleTypes.Utf8, Encoding.UTF8.GetBytes(value, 0, count)); } } } }
/// <summary>Writes an Int32 at the end, and advance the cursor</summary> /// <param name="writer">Target buffer</param> /// <param name="value">Signed DWORD, 32 bits, High Endian</param> public static void WriteInt32(ref TupleWriter writer, int value) { if (value <= 255) { if (value == 0) { // zero writer.Output.WriteByte(FdbTupleTypes.IntZero); return; } if (value > 0) { // 1..255: frequent for array index writer.Output.WriteByte2(FdbTupleTypes.IntPos1, (byte)value); return; } if (value > -256) { // -255..-1 writer.Output.WriteByte2(FdbTupleTypes.IntNeg1, (byte)(255 + value)); return; } } WriteInt64Slow(ref writer, value); }
/// <summary>Serialize a value of type <typeparamref name="T"/> into a tuple segment</summary> /// <param name="value">Value that will be serialized</param> /// <returns>Slice that contains the binary representation of <paramref name="value"/></returns> public static Slice Serialize(T value) { var writer = new TupleWriter(); Encoder(ref writer, value); return(writer.Output.ToSlice()); }
/// <summary>Creates a key range containing all children of tuple, optionally including the tuple itself.</summary> /// <param name="tuple">Tuple that is the prefix of all keys</param> /// <param name="includePrefix">If true, the tuple key itself is included, if false only the children keys are included</param> /// <returns>Range of all keys suffixed by the tuple. The tuple itself will be included if <paramref name="includePrefix"/> is true</returns> public static KeyRange ToRange([NotNull] this ITuple tuple, bool includePrefix) { if (tuple == null) { throw new ArgumentNullException(nameof(tuple)); } // We want to allocate only one byte[] to store both keys, and map both Slice to each chunk // So we will serialize the tuple two times in the same writer var writer = new TupleWriter(); tuple.PackTo(ref writer); writer.Output.EnsureBytes(writer.Output.Position + 2); if (!includePrefix) { writer.Output.WriteByte(0); } int p0 = writer.Output.Position; tuple.PackTo(ref writer); writer.Output.WriteByte(0xFF); int p1 = writer.Output.Position; return(new KeyRange( new Slice(writer.Output.Buffer, 0, p0), new Slice(writer.Output.Buffer, p0, p1 - p0) )); }
private static void WriteUInt64Slow(ref TupleWriter writer, ulong value) { // We are only called for values >= 256 // determine the number of bytes needed to encode the value int bytes = NumberOfBytes(value); writer.Output.EnsureBytes(bytes + 1); var buffer = writer.Output.Buffer; int p = writer.Output.Position; // simple case (ulong can only be positive) buffer[p++] = (byte)(FdbTupleTypes.IntBase + bytes); if (bytes > 0) { // head --bytes; int shift = bytes << 3; while (bytes-- > 0) { buffer[p++] = (byte)(value >> shift); shift -= 8; } // last buffer[p++] = (byte)value; } writer.Output.Position = p; }
public Slice ToSlice() { var writer = new TupleWriter(); PackTo(ref writer); return(writer.Output.ToSlice()); }
public void PackTo(ref TupleWriter writer) { if (m_packed.IsPresent) { writer.Output.WriteBytes(m_packed); } }
/// <summary>Writes a char encoded in UTF-8</summary> public static void WriteChar(ref TupleWriter writer, char value) { if (value == 0) { // NUL => "00 0F" // note: \0 is the only unicode character that will produce a zero byte when converted in UTF-8 writer.Output.WriteByte4(FdbTupleTypes.Utf8, 0x00, 0xFF, 0x00); } else if (value < 0x80) { // 0x00..0x7F => 0xxxxxxx writer.Output.WriteByte3(FdbTupleTypes.Utf8, (byte)value, 0x00); } else if (value < 0x800) { // 0x80..0x7FF => 110xxxxx 10xxxxxx => two bytes writer.Output.WriteByte4(FdbTupleTypes.Utf8, (byte)(0xC0 | (value >> 6)), (byte)(0x80 | (value & 0x3F)), 0x00); } else { // 0x800..0xFFFF => 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // note: System.Char is 16 bits, and thus cannot represent UNICODE chars above 0xFFFF. // => This means that a System.Char will never take more than 3 bytes in UTF-8 ! var tmp = Encoding.UTF8.GetBytes(new string(value, 1)); writer.Output.EnsureBytes(tmp.Length + 2); writer.Output.UnsafeWriteByte(FdbTupleTypes.Utf8); writer.Output.UnsafeWriteBytes(tmp, 0, tmp.Length); writer.Output.UnsafeWriteByte(0x00); } }
public void PackTo(ref TupleWriter writer) { TuplePacker <T1> .Encoder(ref writer, this.Item1); TuplePacker <T2> .Encoder(ref writer, this.Item2); TuplePacker <T3> .Encoder(ref writer, this.Item3); }
public void EncodeKey <T1>(ref SliceWriter writer, T1 item1) { var tw = new TupleWriter(writer); FdbTuplePacker <T1> .SerializeTo(ref tw, item1); writer = tw.Output; }
public Slice ToSlice() { // merge all the slices making up this segment //TODO: should we get the sum of all slices to pre-allocated the buffer ? var writer = new TupleWriter(); PackTo(ref writer); return(writer.Output.ToSlice()); }
public override void EncodeOrderedSelfTerm(ref SliceWriter output, T value) { //HACKHACK: we lose the current depth! var writer = new TupleWriter(output); TuplePacker <T> .Encoder(ref writer, value); output = writer.Output; }
public void PackTo(ref TupleWriter writer) { var slices = m_slices; for (int n = m_count, p = m_offset; n > 0; n--) { writer.Output.WriteBytes(slices[p++]); } }
/// <summary>Writes a binary string</summary> public static void WriteBytes(ref TupleWriter writer, byte[] value) { if (value == null) { WriteNil(ref writer); } else { WriteNulEscapedBytes(ref writer, FdbTupleTypes.Bytes, value); } }
/// <summary>Writes a null value at the end, and advance the cursor</summary> public static void WriteNil(ref TupleWriter writer) { if (writer.Depth == 0) { // at the top level, NILs are escaped as <00> writer.Output.WriteByte(FdbTupleTypes.Nil); } else { // inside a tuple, NILs are escaped as <00><FF> writer.Output.WriteByte2(FdbTupleTypes.Nil, 0xFF); } }
/// <summary>Writes an UInt8 at the end, and advance the cursor</summary> /// <param name="writer">Target buffer</param> /// <param name="value">Unsigned BYTE, 32 bits</param> public static void WriteByte(ref TupleWriter writer, byte value) { if (value == 0) { // zero writer.Output.WriteByte(FdbTupleTypes.IntZero); } else { // 1..255: frequent for array index writer.Output.WriteByte2(FdbTupleTypes.IntPos1, value); } }
/// <summary>Writes a 64-bit UUID</summary> public static void WriteUuid64(ref TupleWriter writer, Uuid64 value) { writer.Output.EnsureBytes(9); writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid64); unsafe { byte *ptr = stackalloc byte[8]; value.WriteTo(ptr); writer.Output.UnsafeWriteBytes(ptr, 8); } }
/// <summary>Writes a RFC 4122 encoded 128-bit UUID</summary> public static void WriteUuid128(ref TupleWriter writer, Uuid128 value) { writer.Output.EnsureBytes(17); writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid128); unsafe { byte *ptr = stackalloc byte[16]; value.WriteTo(ptr); writer.Output.UnsafeWriteBytes(ptr, 16); } }
public void PackTo(ref TupleWriter writer) { FdbTuplePacker <T1> .Encoder(ref writer, this.Item1); FdbTuplePacker <T2> .Encoder(ref writer, this.Item2); FdbTuplePacker <T3> .Encoder(ref writer, this.Item3); FdbTuplePacker <T4> .Encoder(ref writer, this.Item4); FdbTuplePacker <T5> .Encoder(ref writer, this.Item5); }
public static void WriteBool(ref TupleWriter writer, bool value) { // To be compatible with other bindings, we will encode False as the number 0, and True as the number 1 if (value) { // true => 15 01 writer.Output.WriteByte2(FdbTupleTypes.IntPos1, 1); } else { // false => 14 writer.Output.WriteByte(FdbTupleTypes.IntZero); } }
public void EncodeKey <T1, T2, T3>(ref SliceWriter writer, T1 item1, T2 item2, T3 item3) { var tw = new TupleWriter(writer); TuplePacker <T1> .SerializeTo(ref tw, item1); TuplePacker <T2> .SerializeTo(ref tw, item2); TuplePacker <T3> .SerializeTo(ref tw, item3); writer = tw.Output; }
/// <summary>Writes a RFC 4122 encoded 16-byte Microsoft GUID</summary> public static void WriteGuid(ref TupleWriter writer, Guid value) { writer.Output.EnsureBytes(17); writer.Output.UnsafeWriteByte(FdbTupleTypes.Uuid128); unsafe { // UUIDs are stored using the RFC 4122 standard, so we need to swap some parts of the System.Guid byte *ptr = stackalloc byte[16]; Uuid128.Write(value, ptr); writer.Output.UnsafeWriteBytes(ptr, 16); } }
public void EncodeKey <T1, T2, T3, T4, T5>(ref SliceWriter writer, T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) { var tw = new TupleWriter(writer); FdbTuplePacker <T1> .SerializeTo(ref tw, item1); FdbTuplePacker <T2> .SerializeTo(ref tw, item2); FdbTuplePacker <T3> .SerializeTo(ref tw, item3); FdbTuplePacker <T4> .SerializeTo(ref tw, item4); FdbTuplePacker <T5> .SerializeTo(ref tw, item5); writer = tw.Output; }
/// <summary>Writes an UInt64 at the end, and advance the cursor</summary> /// <param name="writer">Target buffer</param> /// <param name="value">Signed QWORD, 64 bits, High Endian</param> public static void WriteUInt64(ref TupleWriter writer, ulong value) { if (value <= 255) { if (value == 0) { // 0 writer.Output.WriteByte(FdbTupleTypes.IntZero); } else { // 1..255 writer.Output.WriteByte2(FdbTupleTypes.IntPos1, (byte)value); } } else { // >= 256 WriteUInt64Slow(ref writer, value); } }
private static void WriteInt64Slow(ref TupleWriter writer, long value) { // we are only called for values <= -256 or >= 256 // determine the number of bytes needed to encode the absolute value int bytes = NumberOfBytes(value); writer.Output.EnsureBytes(bytes + 1); var buffer = writer.Output.Buffer; int p = writer.Output.Position; ulong v; if (value > 0) { // simple case buffer[p++] = (byte)(FdbTupleTypes.IntBase + bytes); v = (ulong)value; } else { // we will encode the one's complement of the absolute value // -1 => 0xFE // -256 => 0xFFFE // -65536 => 0xFFFFFE buffer[p++] = (byte)(FdbTupleTypes.IntBase - bytes); v = (ulong)(~(-value)); } if (bytes > 0) { // head --bytes; int shift = bytes << 3; while (bytes-- > 0) { buffer[p++] = (byte)(v >> shift); shift -= 8; } // last buffer[p++] = (byte)v; } writer.Output.Position = p; }
/// <summary>Writes a buffer with all instances of 0 escaped as '00 FF'</summary> internal static void WriteNulEscapedBytes(ref TupleWriter writer, byte type, [NotNull] byte[] value, int offset, int count) { int n = count; // we need to know if there are any NUL chars (\0) that need escaping... // (we will also need to add 1 byte to the buffer size per NUL) for (int i = offset, end = offset + count; i < end; ++i) { if (value[i] == 0) { ++n; } } writer.Output.EnsureBytes(n + 2); var buffer = writer.Output.Buffer; int p = writer.Output.Position; buffer[p++] = type; if (n > 0) { if (n == count) { // no NULs in the string, can copy all at once SliceHelpers.CopyBytesUnsafe(buffer, p, value, offset, n); p += n; } else { // we need to escape all NULs for (int i = offset, end = offset + count; i < end; ++i) { byte b = value[i]; buffer[p++] = b; if (b == 0) { buffer[p++] = 0xFF; } } } } buffer[p] = 0x00; writer.Output.Position = p + 1; }
/// <summary>Writes an Double at the end, and advance the cursor</summary> /// <param name="writer">Target buffer</param> /// <param name="value">IEEE Floating point, 64 bits, High Endian</param> public static void WriteDouble(ref TupleWriter writer, double value) { // The double is converted to its Big-Endian IEEE binary representation // - If the sign bit is set, flip all the bits // - If the sign bit is not set, just flip the sign bit // This ensures that all negative numbers have their first byte < 0x80, and all positive numbers have their first byte >= 0x80 // Special case for NaN: All variants are normalized to float.NaN ! if (double.IsNaN(value)) { value = double.NaN; } // note: we could use BitConverter.DoubleToInt64Bits(...), but it does the same thing, and also it does not exist for floats... ulong bits; unsafe { bits = *((ulong *)&value); } if ((bits & 0x8000000000000000UL) != 0) { // negative bits = ~bits; } else { // postive bits |= 0x8000000000000000UL; } writer.Output.EnsureBytes(9); var buffer = writer.Output.Buffer; int p = writer.Output.Position; buffer[p] = FdbTupleTypes.Double; buffer[p + 1] = (byte)(bits >> 56); buffer[p + 2] = (byte)(bits >> 48); buffer[p + 3] = (byte)(bits >> 40); buffer[p + 4] = (byte)(bits >> 32); buffer[p + 5] = (byte)(bits >> 24); buffer[p + 6] = (byte)(bits >> 16); buffer[p + 7] = (byte)(bits >> 8); buffer[p + 8] = (byte)(bits); writer.Output.Position = p + 9; }
/// <summary>Writes a buffer with all instances of 0 escaped as '00 FF'</summary> private static void WriteNulEscapedBytes(ref TupleWriter writer, byte type, [NotNull] byte[] value) { int n = value.Length; // we need to know if there are any NUL chars (\0) that need escaping... // (we will also need to add 1 byte to the buffer size per NUL) foreach (byte b in value) { if (b == 0) { ++n; } } writer.Output.EnsureBytes(n + 2); var buffer = writer.Output.Buffer; int p = writer.Output.Position; buffer[p++] = type; if (n > 0) { if (n == value.Length) { // no NULs in the string, can copy all at once SliceHelpers.CopyBytesUnsafe(buffer, p, value, 0, n); p += n; } else { // we need to escape all NULs foreach (byte b in value) { buffer[p++] = b; if (b == 0) { buffer[p++] = 0xFF; } } } } buffer[p++] = 0x00; writer.Output.Position = p; }