// // Copyright (c) Scratch Foundation. All rights reserved. // namespace ScratchLink; using System.Text; using System.Text.Json; using ScratchLink.JsonRpc; /// /// Helpers for interacting with Scratch Link's message buffers. /// A Scratch Link message buffer has a message property and optionally an encoding property. /// If the encoding property is missing, null, or empty, the message is a Unicode string. /// If the encoding property is "base64" then the message is a string in Base64 format. /// No other encodings are supported at this time. /// public static class EncodingHelpers { /// /// Decode the "message" property of into bytes. /// If has an "encoding" property, use that encoding. /// Otherwise, assume the message is Unicode text. /// /// A JSON object containing a "message" property and optionally an "encoding" property. /// An array of bytes containing the decoded data. /// Thrown if the "message" property is missing or the message could not be decoded. public static byte[] DecodeBuffer(JsonElement jsonBuffer) { if (!jsonBuffer.TryGetProperty("message", out var jsonMessage) || jsonMessage.ValueKind != JsonValueKind.String) { throw new JsonRpc2Exception(JsonRpc2Error.InvalidParams("missing or invalid 'message' property")); } jsonBuffer.TryGetProperty("encoding", out var encoding); if (encoding.ValueEquals("base64")) { if (jsonMessage.TryGetBytesFromBase64(out var messageBytes)) { return messageBytes; } throw new JsonRpc2Exception(JsonRpc2Error.ParseError("failed to parse base64 message")); } else if (encoding.ValueKind == JsonValueKind.Undefined || encoding.ValueKind == JsonValueKind.Null) { // message is a Unicode string with no additional encoding return Encoding.UTF8.GetBytes(jsonMessage.GetString()); } throw new JsonRpc2Exception(JsonRpc2Error.InvalidParams($"unsupported encoding: {encoding}")); } /// /// Encode using and return the result as a string. /// /// The bytes to encode. /// The encoding format, or null to "encode" UTF-8 data as a Unicode string. /// A string containing the encoded data. /// Thrown if the data could not be encoded, including if the encoding is not supported. public static string EncodeBuffer(byte[] data, string encoding) { switch (encoding) { case "base64": return Convert.ToBase64String(data); case null: return Encoding.UTF8.GetString(data); default: throw new JsonRpc2Exception(JsonRpc2Error.InvalidParams($"unsupported encoding: {encoding}")); } } }