Skip to content
This repository has been archived by the owner on May 27, 2022. It is now read-only.

Implement C# Generation and Runtime #71

Merged
merged 43 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
398057b
Port Java codegen and runtime to C#
mattico Nov 7, 2020
80534c0
Add C# support to serdegen
mattico Nov 10, 2020
5b70b42
Rustfmt
mattico Nov 10, 2020
49037dd
csharp: remove Builder
mattico Nov 11, 2020
4dc09ff
csharp: Add specialized c-style enum serialization
mattico Nov 11, 2020
5a8f633
csharp: change to .NET Standard 1.6
mattico Nov 11, 2020
0b84725
csharp: Fix jagged array initialization and c-style enums
mattico Nov 11, 2020
ec322fa
csharp: Fix enum ser/de using extension class
mattico Nov 12, 2020
15a1c97
csharp: use SerializationException in serialization helper
mattico Nov 12, 2020
f3defad
csharp: Fix array deser helper indent
mattico Nov 12, 2020
a631062
csharp: Don't emit Rune
mattico Nov 12, 2020
94f47de
csharp: Fixup generation to match simplified runtime
mattico Nov 12, 2020
62819ab
csharp: Add ser/de impls for ArraySegment
mattico Nov 12, 2020
48ca2bc
csharp: Use random starting value for GetHashCode to prevent structur…
mattico Nov 13, 2020
77a9cd2
Rustfmt
mattico Nov 13, 2020
fa0c8c4
csharp: Use SequenceEqual for other enumerables
mattico Nov 13, 2020
9c9fb68
csharp: Add CI
mattico Nov 13, 2020
b341423
csharp: Fix clippy warnings
mattico Nov 13, 2020
7aa3b31
csharp: Fix runtime directory case insensitive error
mattico Nov 13, 2020
b2f8f01
csharp: Format runtime
mattico Nov 13, 2020
d6606b3
csharp: Implement float ser/de in runtime
mattico Nov 13, 2020
8c2ff6d
csharp: Use ImmutableArray<byte> for byte array type
mattico Nov 16, 2020
173b03e
csharp: Add config value to enable c-style-enums
mattico Nov 16, 2020
785c2cf
csharp: Hack to fix CI failures
mattico Nov 16, 2020
b548269
csharp: Don't use random values to initialize hashcode
mattico Nov 17, 2020
ec98362
csharp: Address review feedback
mattico Nov 17, 2020
d414c85
serdegen: Add --c-style-enums argument
mattico Nov 18, 2020
60e0fda
csharp: No longer need runtime-testing
mattico Nov 18, 2020
a826d54
csharp: Test for value-equality of generated types
mattico Nov 18, 2020
a6099bb
Add some checking for languages that don't support c-style-enums
mattico Nov 18, 2020
098158a
test_utils: Add C-style enum type for testing
mattico Nov 19, 2020
349258e
serdegen: Improve c-style enum option
mattico Nov 19, 2020
ba496a4
test_utils: Update other tests for added CStyleEnum
mattico Nov 19, 2020
16ec55d
test_utils: Add test for nested Vec
mattico Nov 19, 2020
d215954
csharp: Fix Equals() null test
mattico Nov 19, 2020
b8a44d9
csharp: Fix test project
mattico Nov 19, 2020
b99f9ca
csharp: Fix serialize_u128 assert
mattico Nov 19, 2020
3724ce8
csharp: improve runtime test generation
mattico Nov 19, 2020
6cc76fb
csharp: Improve nullability check
mattico Nov 20, 2020
65d8eca
csharp: Fix bigint serialization
mattico Nov 23, 2020
2e439fb
csharp: Use value type wrapper containers
mattico Nov 24, 2020
da81367
rust: clippy
mattico Nov 24, 2020
75e0736
csharp: Make Unit a readonly struct
mattico Nov 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,21 @@ jobs:
name: Setup Additional Languages
command: |
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install python3-all-dev python3-pip python3-numpy clang llvm default-jdk
sudo apt-get install -y apt-transport-https python3-all-dev python3-pip python3-numpy clang llvm default-jdk
python3 -m pip install pyre-check
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
nvm install v12.18.0
echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV
echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV
wget https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y dotnet-sdk-2.1
- run:
name: Version Information
command: rustc --version; cargo --version; rustup --version; python3 --version; clang++ --version; javac -version; go version; echo "node $(node -v)"; echo "npm $(npm -v)"
command: rustc --version; cargo --version; rustup --version; python3 --version; clang++ --version; javac -version; go version; echo "node $(node -v)"; echo "npm $(npm -v)"; dotnet --list-sdks
- run:
name: Setup Env
command: |
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ __pycache__
.class
.o
.idea
obj/
bin/
.vs/
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions serde-generate/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ bincode = { version = "1.3.1" }
libra-canonical-serialization = { version = "0.1.0" }

[dev-dependencies]
lazy_static = "1"
tempfile = "3.1"
hex = "0.4.2"
which = "4.0.2"
Expand Down
21 changes: 21 additions & 0 deletions serde-generate/runtime/csharp/Serde.Tests/Serde.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>

<IsPackable>false</IsPackable>

<LangVersion>7.2</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Serde\Serde.csproj" />
</ItemGroup>

</Project>
81 changes: 81 additions & 0 deletions serde-generate/runtime/csharp/Serde.Tests/TestLcs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Numerics;
using NUnit.Framework;
using Serde.Lcs;

namespace Serde.Tests
{
public class TestLcs
{
[Test]
public void TestSerializeU128()
{
LcsSerializer serializer = new LcsSerializer();
serializer.serialize_u128((BigInteger.One << 128) - 1);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 });

serializer = new LcsSerializer();
serializer.serialize_u128(BigInteger.One);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

serializer = new LcsSerializer();
serializer.serialize_u128(BigInteger.Zero);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

Assert.Throws<ArgumentOutOfRangeException>(() => serializer.serialize_u128(BigInteger.MinusOne));

Assert.Throws<ArgumentOutOfRangeException>(() => serializer.serialize_u128((BigInteger.One << 128) + 1));
}

[Test]
public void TestSerializeI128()
{
LcsSerializer serializer = new LcsSerializer();
serializer.serialize_i128(BigInteger.MinusOne);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 });

serializer = new LcsSerializer();
serializer.serialize_i128(BigInteger.One);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });

serializer = new LcsSerializer();
serializer.serialize_i128((BigInteger.One << 127) - 1);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127 });

serializer = new LcsSerializer();
serializer.serialize_i128(-(BigInteger.One << 127));
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80 });

Assert.Throws<ArgumentOutOfRangeException>(() => serializer.serialize_i128(BigInteger.One << 127));

Assert.Throws<ArgumentOutOfRangeException>(() => serializer.serialize_i128(-((BigInteger.One << 127) + 1)));
}

[Test]
public void TestSliceOrdering()
{
LcsSerializer serializer = new LcsSerializer();
serializer.serialize_u8(255);
serializer.serialize_u32(1);
serializer.serialize_u32(1);
serializer.serialize_u32(2);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 255, /**/ 1, /**/ 0, 0, /**/ 0, 1, 0, /**/ 0, /**/ 0, /**/ 2, 0, 0, 0 });

int[] offsets = { 1, 2, 4, 7, 8, 9 };
serializer.sort_map_entries(offsets);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 255, /**/ 0, /**/ 0, /**/ 0, 0, /**/ 0, 1, 0, /**/ 1, /**/ 2, 0, 0, 0 });
}

[Test]
public void TestULEB128Encoding()
{
LcsSerializer serializer = new LcsSerializer();
serializer.serialize_len(0);
serializer.serialize_len(1);
serializer.serialize_len(127);
serializer.serialize_len(128);
serializer.serialize_len(3000);
CollectionAssert.AreEqual(serializer.get_bytes(), new byte[] { 0, 1, 127, 128, 1, 184, 23 });
}
}
}
143 changes: 143 additions & 0 deletions serde-generate/runtime/csharp/Serde/BinaryDeserializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright (c) Facebook, Inc. and its affiliates
// SPDX-License-Identifier: MIT OR Apache-2.0

using System;
using System.Collections.Immutable;
using System.IO;
using System.Numerics;
using System.Text;

namespace Serde
{
public abstract class BinaryDeserializer : IDeserializer, IDisposable
{
protected readonly ArraySegment<byte> input;
protected readonly BinaryReader reader;
protected readonly Encoding utf8 = Encoding.GetEncoding("utf-8", new EncoderExceptionFallback(), new DecoderExceptionFallback());
private long containerDepthBudget;

public BinaryDeserializer(byte[] _input, long maxContainerDepth) : this(new ArraySegment<byte>(_input), maxContainerDepth) { }

public BinaryDeserializer(ArraySegment<byte> _input, long maxContainerDepth)
{
input = _input;
reader = new BinaryReader(new MemoryStream(input.Array, input.Offset, input.Count));
containerDepthBudget = maxContainerDepth;
}

public void Dispose() => reader.Dispose();

public int get_buffer_offset() => (int)reader.BaseStream.Position;

public abstract long deserialize_len();
public abstract int deserialize_variant_index();
public abstract void check_that_key_slices_are_increasing(Range key1, Range key2);

public char deserialize_char() => throw new DeserializationException("Not implemented: char deserialization");

public float deserialize_f32() => reader.ReadSingle();

public double deserialize_f64() => reader.ReadDouble();

public void increase_container_depth()
{
if (containerDepthBudget == 0)
{
throw new DeserializationException("Exceeded maximum container depth");
}
containerDepthBudget -= 1;
}

public void decrease_container_depth()
{
containerDepthBudget += 1;
}

public string deserialize_str()
{
long len = deserialize_len();
if (len < 0 || len > int.MaxValue)
{
throw new DeserializationException("Incorrect length value for C# string");
}
byte[] content = reader.ReadBytes((int)len);
if (content.Length < len)
throw new DeserializationException($"Need {len - content.Length} more bytes for string");
return utf8.GetString(content);
}

public ImmutableArray<byte> deserialize_bytes()
{
long len = deserialize_len();
if (len < 0 || len > int.MaxValue)
{
throw new DeserializationException("Incorrect length value for C# array");
}
byte[] content = reader.ReadBytes((int)len);
if (content.Length < len)
throw new DeserializationException($"Need {len - content.Length} more bytes for byte array");
return ImmutableArray.CreateRange<byte>(content);
}

public bool deserialize_bool()
{
byte value = reader.ReadByte();
switch (value)
{
case 0: return false;
case 1: return true;
default: throw new DeserializationException("Incorrect value for bool: " + value);
}
}

public Unit deserialize_unit() => new Unit();

public byte deserialize_u8() => reader.ReadByte();

public ushort deserialize_u16() => reader.ReadUInt16();

public uint deserialize_u32() => reader.ReadUInt32();

public ulong deserialize_u64() => reader.ReadUInt64();

public BigInteger deserialize_u128()
{
BigInteger signed = deserialize_i128();
if (signed >= 0)
{
return signed;
}
else
{
return signed + (BigInteger.One << 128);
}
}

public sbyte deserialize_i8() => reader.ReadSByte();

public short deserialize_i16() => reader.ReadInt16();

public int deserialize_i32() => reader.ReadInt32();

public long deserialize_i64() => reader.ReadInt64();

public BigInteger deserialize_i128()
{
byte[] content = reader.ReadBytes(16);
if (content.Length < 16)
throw new DeserializationException("Need more bytes to deserialize 128-bit integer");
return new BigInteger(content);
}

public bool deserialize_option_tag()
{
byte value = reader.ReadByte();
switch (value)
{
case 0: return false;
case 1: return true;
default: throw new DeserializationException("Incorrect value for Option tag: " + value);
}
}
}
}
Loading