Exemplo n.º 1
0
        private RequestHandle <TResult> RequestAsyncCore <TParams, TResult>(EscapedUTF8String methodName, TParams parameters, IJsonFormatterResolver formatterResolver, IErrorHandler errorHandler, CancellationToken cancellationToken = default)
        {
            var idNum = Interlocked.Increment(ref this.id);
            var id    = new ID(idNum);

            if (cancellationToken.CanBeCanceled)
            {
                RegisterCancellation(id, cancellationToken);//ラムダ式のクロージャ生成を遅延
            }
            var request = new Request <TParams>()
            {
                ID = id, Method = methodName, Params = parameters
            };
            var serializedRequest = JsonSerializer.SerializeUnsafe(request, formatterResolver).CopyToPooled();
            var handle            = RequestHandle <TResult> .Create(serializedRequest, errorHandler);

            if (!UnResponsedRequests.TryAdd(idNum, handle))
            {
                Debug.Fail("ID conflicted.");
            }
            _ = MessageChannel.Writer.WriteAsync(handle);



            return(handle);
        }
Exemplo n.º 2
0
 public RpcMethodHandle(RpcDomain domain, string name, IJsonFormatterResolver jsonFormatterResolver, IErrorHandler errorHandler)
 {
     Name                  = name;
     EscapedUTF8Name       = EscapedUTF8String.FromUnEscaped(name);
     Domain                = domain;
     JsonFormatterResolver = jsonFormatterResolver;
     ErrorHandler          = errorHandler;
 }
Exemplo n.º 3
0
        internal ValueTask NotifyAsync <TParams>(EscapedUTF8String methodName, TParams parameters, IJsonFormatterResolver formatterResolver)
        {
            var serializedNotification = JsonSerializer.SerializeUnsafe(new Notification <TParams>()
            {
                Method = methodName, Params = parameters
            }, formatterResolver).CopyToPooled();
            var handle = SendMessageHandle.Create(serializedNotification);

            _ = MessageChannel.Writer.WriteAsync(handle);
            return(handle.Task);
        }
Exemplo n.º 4
0
        private static UTF8String UnEscape(EscapedUTF8String escaped)
        {
            bool shouldReturn = UnEscapeUnsafe(escaped, out var str);

            UTF8String ret = str.Clone();

            if (shouldReturn)
            {
                ArrayPool <byte> .Shared.Return(str.bytes.Array !);
            }
            return(ret);
        }
Exemplo n.º 5
0
        /// <summary>
        /// trueを返した場合、<see cref="ArrayPool{byte}.Shared"/>に内部バッファを返還する必要があり、また返還するまでは永久に使用可能です。
        /// falseを返した場合、<see cref="ArrayPool{byte}.Shared"/>に内部バッファを返還する必要はありませんが、ヒープに保存することができません。
        /// </summary>
        /// <param name="escaped"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool UnEscapeUnsafe(EscapedUTF8String escaped, out UTF8String str)
        {
            var quoted = escaped.GetQuoted();
            var reader = new JsonReader(quoted.Array, quoted.Offset);

            var segment = reader.ReadStringSegmentUnsafe();

            str = new UTF8String(segment);
            if (quoted.Array == segment.Array)
            {
                return(true);
            }
            else
            {
                ArrayPool <byte> .Shared.Return(quoted.Array !);

                return(false);
            }
        }
Exemplo n.º 6
0
 public bool RemoveMethod(string name, [NotNullWhen(true)] out RpcAsyncMethodEntry?methodEntry)
 {
     return(MethodEntries.TryRemove(EscapedUTF8String.FromUnEscaped(name), out methodEntry));
 }
Exemplo n.º 7
0
 public bool AddMethod(string name, RpcAsyncMethodEntry methodEntry)
 {
     return(MethodEntries.TryAdd(EscapedUTF8String.FromUnEscaped(name), methodEntry));
 }
Exemplo n.º 8
0
        internal ValueTask <TResult> RequestAsync <TParams, TResult>(EscapedUTF8String methodName, TParams parameters, IJsonFormatterResolver formatterResolver, IErrorHandler errorHandler, CancellationToken cancellationToken = default)
        {
            var handle = RequestAsyncCore <TParams, TResult>(methodName, parameters, formatterResolver, errorHandler, cancellationToken);

            return(handle.Task);
        }
Exemplo n.º 9
0
        public static MessageParseResult ParseDuplexMessage(ArraySegment <byte> message)
        {
            var parseResult = new MessageParseResult();
            var reader      = new JsonReader(message.Array !, message.Offset);

            if (reader.ReadIsBeginObject())
            {
                try
                {
                    while (true)
                    {
                        reader.SkipWhiteSpace();
                        var         buffer    = reader.GetBufferUnsafe().AsSpan(reader.GetCurrentOffsetUnsafe());
                        ref var     bufferRef = ref MemoryMarshal.GetReference(buffer);
                        const uint  id        = (('"') | ('i' << 8) | ('d' << 16) | ('"' << 24));
                        const ulong method    = ((ulong)'"') | ((ulong)'m' << 8) | ((ulong)'e' << 16) | ((ulong)'t' << 24) | ((ulong)'h' << 32) | ((ulong)'o' << 40) | ((ulong)'d' << 48) | ((ulong)'"' << 56);
                        const ulong @params   = ((ulong)'"') | ((ulong)'p' << 8) | ((ulong)'a' << 16) | ((ulong)'r' << 24) | ((ulong)'a' << 32) | ((ulong)'m' << 40) | ((ulong)'s' << 48) | ((ulong)'"' << 56);
                        const ulong jsonrpc   = (((ulong)'"') | ((ulong)'j' << 8) | ((ulong)'s' << 16) | ((ulong)'o' << 24) | ((ulong)'n' << 32) | ((ulong)'r' << 40) | ((ulong)'p' << 48) | ((ulong)'c' << 56));
                        const ulong ___2_0    = (((ulong)'"') | ((ulong)'2' << 8) | ((ulong)'.' << 16) | ((ulong)'0' << 24) | ((ulong)'"' << 32)) << 24;
                        const ulong result    = (((ulong)'"') | ((ulong)'r' << 8) | ((ulong)'e' << 16) | ((ulong)'s' << 24) | ((ulong)'u' << 32) | ((ulong)'l' << 40) | ((ulong)'t' << 48) | ((ulong)'"' << 56));
                        const ulong error     = (((ulong)'"') | ((ulong)'e' << 8) | ((ulong)'r' << 16) | ((ulong)'r' << 24) | ((ulong)'o' << 32) | ((ulong)'r' << 40) | ((ulong)'"' << 48));

                        switch (buffer.Length)
                        {
                        case 0:
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                            goto UnknownProperty;

                        //最短の正常な文字列パターンは"id":1}で7byteある
                        case 7:
                        case 8:
                        case 9:
                        case 10:

                        {
                            if (Unsafe.ReadUnaligned <uint>(ref bufferRef) == id)
                            {
                                goto ID;
                            }
                            else
                            {
                                goto UnknownProperty;
                            }
                        }

                        case 11:
                        {
                            var chars8 = Unsafe.ReadUnaligned <ulong>(ref bufferRef);

                            if ((uint)chars8 == id)
                            {
                                goto ID;
                            }
                            else if ((chars8 & (ulong)0x00FFFFFFFFFFFFFF) == error)
                            {
                                goto Error;
                            }
                            else
                            {
                                goto UnknownProperty;
                            }
                        }

                        //その次に短いのは"params":[]}または"params":{}}または"method":""または"result":1}
                        case 12:
                        case 13:
                        case 14:
                        case 15:
                        {
                            var chars8 = Unsafe.ReadUnaligned <ulong>(ref bufferRef);
                            switch (chars8)
                            {
                            case result:
                            {
                                goto Result;
                            }

                            case method:
                            {
                                goto Method;
                            }

                            case @params:
                            {
                                goto Params;
                            }

                            default:
                            {
                                if ((uint)chars8 == id)
                                {
                                    goto ID;
                                }
                                else if ((chars8 & (ulong)0x00FFFFFFFFFFFFFF) == error)
                                {
                                    goto Error;
                                }
                                else
                                {
                                    goto UnknownProperty;
                                }
                            }
                            }
                        }

                        //その次が"jsonrpc":"2.0"}
                        default:
                        {
                            var chars8 = Unsafe.ReadUnaligned <ulong>(ref bufferRef);
                            switch (chars8)
                            {
                            case jsonrpc:
                            {
                                goto JsonRpc;
                            }

                            case result:
                            {
                                goto Result;
                            }

                            case method:
                            {
                                goto Method;
                            }

                            case @params:
                            {
                                goto Params;
                            }

                            default:
                            {
                                if ((uint)chars8 == id)
                                {
                                    goto ID;
                                }
                                else if ((chars8 & (ulong)0x00FFFFFFFFFFFFFF) == error)
                                {
                                    goto Error;
                                }
                                else
                                {
                                    goto UnknownProperty;
                                }
                            }
                            }
                        }
JsonRpc:
                            {
                                if (Unsafe.AddByteOffset(ref bufferRef, (IntPtr)(8)) == (byte)'"')
                                {
                                    reader.AdvanceOffset(9);
                                    if (reader.ReadIsNameSeparator())
                                    {
                                        reader.SkipWhiteSpace();
                                        buffer    = reader.GetBufferUnsafe().AsSpan(reader.GetCurrentOffsetUnsafe());
                                        bufferRef = ref MemoryMarshal.GetReference(buffer);
                                        if ((Unsafe.ReadUnaligned <ulong>(ref Unsafe.AddByteOffset(ref bufferRef, (IntPtr)(-3))) & 0xFFFFFFFFFF000000) == ___2_0)
                                        {
                                            reader.AdvanceOffset(5);
                                            parseResult[MessagePropertyKind.JsonRpcVersion] = PropertyState.Valid;
                                            break;
                                        }
                                        else
                                        {
                                            goto UnExpectedFormatProperty;
                                        }
                                    }
                                    else
                                    {
                                        goto InvalidJson;
                                    }
                                }
                                else
                                {
                                    goto UnknownProperty;
                                }
                            }
Method:
                            {
                                reader.AdvanceOffset(8);
                                if (reader.ReadIsNameSeparator())
                                {
                                    try
                                    {
                                        parseResult.Method = EscapedUTF8String.FromEscapedNonQuoted(reader.ReadStringSegmentRaw());
                                    }
                                    catch (JsonParsingException)
                                    {
                                        parseResult[MessagePropertyKind.Method] = PropertyState.Invalid;
                                        goto UnExpectedFormatProperty;
                                    }
                                    parseResult[MessagePropertyKind.Method] = PropertyState.Valid;
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
Params:
                            {
                                reader.AdvanceOffset(8);
                                if (reader.ReadIsNameSeparator())
                                {
                                    try
                                    {
                                        parseResult.Params = reader.ReadNextBlockSegment();
                                    }
                                    catch (JsonParsingException)
                                    {
                                        parseResult[MessagePropertyKind.Params] = PropertyState.Invalid;
                                        goto UnExpectedFormatProperty;
                                    }
                                    parseResult[MessagePropertyKind.Params] = PropertyState.Valid;
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
ID:
                            {
                                reader.AdvanceOffset(4);
                                if (reader.ReadIsNameSeparator())
                                {
                                    try
                                    {
                                        parseResult.id = ID.Formatter.DeserializeNullableSafe(ref reader);
                                    }
                                    catch (JsonParsingException)
                                    {
                                        parseResult[MessagePropertyKind.ID] = PropertyState.Invalid;
                                        goto UnExpectedFormatProperty;
                                    }
                                    parseResult[MessagePropertyKind.ID] = PropertyState.Valid;
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
Result:
                            {
                                reader.AdvanceOffset(8);
                                if (reader.ReadIsNameSeparator())
                                {
                                    try
                                    {
                                        parseResult.Result = reader.ReadNextBlockSegment();
                                    }
                                    catch (JsonParsingException)
                                    {
                                        parseResult[MessagePropertyKind.Result] = PropertyState.Invalid;
                                        goto UnExpectedFormatProperty;
                                    }
                                    parseResult[MessagePropertyKind.Result] = PropertyState.Valid;
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
Error:
                            {
                                reader.AdvanceOffset(7);
                                if (reader.ReadIsNameSeparator())
                                {
                                    try
                                    {
                                        parseResult.Error = reader.ReadNextBlockSegment();     //Client.JsonResolver.GetFormatterWithVerify<Client.ResponseError<object?>>().Deserialize(ref reader, Client.JsonResolver);
                                    }
                                    catch (JsonParsingException)
                                    {
                                        parseResult[MessagePropertyKind.Error] = PropertyState.Invalid;
                                        goto UnExpectedFormatProperty;
                                    }
                                    parseResult[MessagePropertyKind.Error] = PropertyState.Valid;
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
UnknownProperty:
                            {
                                parseResult.ParseErrors |= MessageParseErrors.HasUnknownProperty;
                                try
                                {
                                    reader.ReadStringSegmentRaw();
                                }
                                catch (JsonParsingException)
                                {
                                    goto InvalidJson;
                                }

                                if (reader.ReadIsValueSeparator())
                                {
                                    try
                                    {
                                        reader.ReadNextBlock();
                                    }
                                    catch (JsonParsingException)
                                    {
                                        goto InvalidJson;
                                    }
                                    break;
                                }
                                else
                                {
                                    goto InvalidJson;
                                }
                            }
UnExpectedFormatProperty:
                            {
                                parseResult.ParseErrors = MessageParseErrors.HasInvalidProperty;
                                try
                                {
                                    reader.ReadNextBlock();
                                }
                                catch (JsonParsingException)
                                {
                                    goto InvalidJson;
                                }
                                break;
                            }
                        }
                        switch (reader.GetCurrentJsonToken())
                        {
                        case JsonToken.ValueSeparator:
                        {
                            reader.AdvanceOffset(1);
                            continue;
                        }

                        case JsonToken.EndObject:
                        {
                            return(parseResult);
                        }

                        default:
                            goto InvalidJson;
                        }
                    }
                }
Exemplo n.º 10
0
 public ID(EscapedUTF8String id)
 {
     String      = id;
     numberValue = default;
 }