Skip to content

Commit d5416af

Browse files
Copilotstephentoub
andcommitted
Use reader.GetBytesFromBase64() with FromBytes() for escaped base64 data
When JSON-escaped base64 data is present, use reader.GetBytesFromBase64() to directly decode to bytes instead of going through an intermediate string with GetString() + Encoding.UTF8.GetBytes(). Then use FromBytes() factory methods which cache the decoded data and lazily encode to base64 UTF-8, avoiding unnecessary intermediate allocations. Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
1 parent b386e0a commit d5416af

2 files changed

Lines changed: 28 additions & 15 deletions

File tree

src/ModelContextProtocol.Core/Protocol/ContentBlock.cs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Diagnostics;
55
using System.Diagnostics.CodeAnalysis;
66
using System.Runtime.InteropServices;
7-
using System.Text;
87
using System.Text.Json;
98
using System.Text.Json.Nodes;
109
using System.Text.Json.Serialization;
@@ -93,6 +92,7 @@ public sealed class Converter : JsonConverter<ContentBlock>
9392
string? name = null;
9493
string? title = null;
9594
ReadOnlyMemory<byte>? data = null;
95+
ReadOnlyMemory<byte>? decodedData = null;
9696
string? mimeType = null;
9797
string? uri = null;
9898
string? description = null;
@@ -144,7 +144,7 @@ public sealed class Converter : JsonConverter<ContentBlock>
144144
}
145145
else
146146
{
147-
data = Encoding.UTF8.GetBytes(reader.GetString()!);
147+
decodedData = reader.GetBytesFromBase64();
148148
}
149149
break;
150150

@@ -238,17 +238,23 @@ public sealed class Converter : JsonConverter<ContentBlock>
238238
Text = text ?? throw new JsonException("Text contents must be provided for 'text' type."),
239239
},
240240

241-
"image" => new ImageContentBlock
242-
{
243-
Data = data ?? throw new JsonException("Image data must be provided for 'image' type."),
244-
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'image' type."),
245-
},
246-
247-
"audio" => new AudioContentBlock
248-
{
249-
Data = data ?? throw new JsonException("Audio data must be provided for 'audio' type."),
250-
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'audio' type."),
251-
},
241+
"image" => decodedData is not null ?
242+
ImageContentBlock.FromBytes(decodedData.Value,
243+
mimeType ?? throw new JsonException("MIME type must be provided for 'image' type.")) :
244+
new ImageContentBlock
245+
{
246+
Data = data ?? throw new JsonException("Image data must be provided for 'image' type."),
247+
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'image' type."),
248+
},
249+
250+
"audio" => decodedData is not null ?
251+
AudioContentBlock.FromBytes(decodedData.Value,
252+
mimeType ?? throw new JsonException("MIME type must be provided for 'audio' type.")) :
253+
new AudioContentBlock
254+
{
255+
Data = data ?? throw new JsonException("Audio data must be provided for 'audio' type."),
256+
MimeType = mimeType ?? throw new JsonException("MIME type must be provided for 'audio' type."),
257+
},
252258

253259
"resource" => new EmbeddedResourceBlock
254260
{

src/ModelContextProtocol.Core/Protocol/ResourceContents.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.ComponentModel;
33
using System.Diagnostics;
44
using System.Diagnostics.CodeAnalysis;
5-
using System.Text;
65
using System.Text.Json;
76
using System.Text.Json.Nodes;
87
using System.Text.Json.Serialization;
@@ -81,6 +80,7 @@ public sealed class Converter : JsonConverter<ResourceContents>
8180
string? uri = null;
8281
string? mimeType = null;
8382
ReadOnlyMemory<byte>? blob = null;
83+
ReadOnlyMemory<byte>? decodedBlob = null;
8484
string? text = null;
8585
JsonObject? meta = null;
8686

@@ -112,7 +112,7 @@ public sealed class Converter : JsonConverter<ResourceContents>
112112
}
113113
else
114114
{
115-
blob = Encoding.UTF8.GetBytes(reader.GetString()!);
115+
decodedBlob = reader.GetBytesFromBase64();
116116
}
117117
break;
118118

@@ -130,6 +130,13 @@ public sealed class Converter : JsonConverter<ResourceContents>
130130
}
131131
}
132132

133+
if (decodedBlob is not null)
134+
{
135+
var blobResource = BlobResourceContents.FromBytes(decodedBlob.Value, uri ?? string.Empty, mimeType);
136+
blobResource.Meta = meta;
137+
return blobResource;
138+
}
139+
133140
if (blob is not null)
134141
{
135142
return new BlobResourceContents

0 commit comments

Comments
 (0)