-
-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathNdefMessage.cs
166 lines (145 loc) · 5.23 KB
/
NdefMessage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
namespace Iot.Device.Ndef
{
/// <summary>
/// Create a NDEF = NFC Data Exchange Format Message class
/// </summary>
public class NdefMessage
{
/// <summary>
/// Associated with the GeneralPurposeByteConsitions, it tells if a sector is read/write and a valid
/// NDEF sector
/// </summary>
public const byte GeneralPurposeByteNdefVersion = 0b0100_0000;
/// <summary>
/// From a raw message, find the start and stop of an NDEF message
/// </summary>
/// <param name="toExtract">The byte array where the message is</param>
/// <returns>The start and end position</returns>
public static Doublet GetStartSizeNdef(SpanByte toExtract)
{
int idx = 0;
// Check if we have 0x03 so it's a possible, NDEF Entry
while (idx < toExtract.Length)
{
if (toExtract[idx++] == 0x03)
{
break;
}
}
if (idx == toExtract.Length)
{
return new Doublet(-1, -1);
}
// Now check the size. If 0xFF then encoding is on 3 bytes otherwise just one
int size = toExtract[idx++];
if (idx == toExtract.Length)
{
return new Doublet(idx, -1);
}
if (size == 0xFF)
{
if (idx + 2 >= toExtract.Length)
{
return new Doublet(idx, -1);
}
size = (toExtract[idx++] << 8) + toExtract[idx++];
}
return new Doublet(idx, size);
}
/// <summary>
/// Extract an NDEF message from a raw byte array
/// </summary>
/// <param name="toExtract">The byte array where the message is</param>
/// <returns>A byte array containing the message itself</returns>
public static byte[]? ExtractMessage(SpanByte toExtract)
{
var doublet = GetStartSizeNdef(toExtract);
int idx = doublet.Start;
int size = doublet.Size;
// Finally check that the end terminator TLV is 0xFE
bool isRealEnd = toExtract[idx + size] == 0xFE;
if (!isRealEnd)
{
return new byte[0];
}
// Now we have the real size and we can extract the real buffer
byte[] toReturn = new byte[size];
toExtract.Slice(idx, size).CopyTo(toReturn);
return toReturn;
}
/// <summary>
/// List of all NDEF Records
/// </summary>
public ListNdefRecord Records { get; set; } = new ListNdefRecord();
/// <summary>
/// Create an empty NDEF Message
/// </summary>
public NdefMessage()
{
}
/// <summary>
/// Create NDEF Message from a span of bytes
/// </summary>
/// <param name="message">the message in span of bytes</param>
public NdefMessage(SpanByte message)
{
int idxMessage = 0;
while (idxMessage < message.Length)
{
var ndefrec = new NdefRecord(message.Slice(idxMessage));
Records.Add(ndefrec);
idxMessage += ndefrec.Length;
}
}
/// <summary>
/// Get the length of the message
/// </summary>
public int Length
{
get
{
// Ogiginal: => Records.Select(m => m.Length).Sum();
int sum = 0;
for (int i = 0; i < Records.Count; i++)
{
sum += Records[i].Length;
}
return sum;
}
}
/// <summary>
/// Serialize the message in a span of bytes
/// </summary>
/// <param name="messageSerialized">Span of bytes for the serialized message</param>
public void Serialize(SpanByte messageSerialized)
{
if (messageSerialized.Length < Length)
{
throw new ArgumentException($"Span of bytes needs to be at least as large as the Message total length");
}
if (Records.Count == 0)
{
return;
}
// Make sure we set correctly the Begin and End message flags
Records[0].Header.MessageFlag |= MessageFlag.MessageBegin;
Records[0].Header.MessageFlag &= ~MessageFlag.MessageEnd;
Records[Records.Count - 1].Header.MessageFlag |= MessageFlag.MessageEnd;
int idx = 0;
for (int i = 0; i < Records.Count; i++)
{
if ((i != 0) && (i != (Records.Count - 1)))
{
Records[i].Header.MessageFlag &= ~MessageFlag.MessageBegin;
Records[i].Header.MessageFlag &= ~MessageFlag.MessageEnd;
}
Records[i].Serialize(messageSerialized.Slice(idx));
idx += Records[i].Length;
}
}
}
}