File size: 3,997 Bytes
05c9ac2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System;
using System.IO;
using System.Text;

namespace Unity.MLAgents.SideChannels
{
    /// <summary>
    /// Utility class for reading the data sent to the SideChannel.
    /// </summary>
    public class IncomingMessage : IDisposable
    {
        byte[] m_Data;
        Stream m_Stream;
        BinaryReader m_Reader;

        /// <summary>
        /// Construct an IncomingMessage from the byte array.
        /// </summary>
        /// <param name="data"></param>
        public IncomingMessage(byte[] data)
        {
            m_Data = data;
            m_Stream = new MemoryStream(data);
            m_Reader = new BinaryReader(m_Stream);
        }

        /// <summary>
        /// Read a boolean value from the message.
        /// </summary>
        /// <param name="defaultValue">Default value to use if the end of the message is reached.</param>
        /// <returns></returns>
        public bool ReadBoolean(bool defaultValue = false)
        {
            return CanReadMore() ? m_Reader.ReadBoolean() : defaultValue;
        }

        /// <summary>
        /// Read an integer value from the message.
        /// </summary>
        /// <param name="defaultValue">Default value to use if the end of the message is reached.</param>
        /// <returns></returns>
        public int ReadInt32(int defaultValue = 0)
        {
            return CanReadMore() ? m_Reader.ReadInt32() : defaultValue;
        }

        /// <summary>
        /// Read a float value from the message.
        /// </summary>
        /// <param name="defaultValue">Default value to use if the end of the message is reached.</param>
        /// <returns></returns>
        public float ReadFloat32(float defaultValue = 0.0f)
        {
            return CanReadMore() ? m_Reader.ReadSingle() : defaultValue;
        }

        /// <summary>
        /// Read a string value from the message.
        /// </summary>
        /// <param name="defaultValue">Default value to use if the end of the message is reached.</param>
        /// <returns></returns>
        public string ReadString(string defaultValue = default)
        {
            if (!CanReadMore())
            {
                return defaultValue;
            }

            var strLength = ReadInt32();
            var str = Encoding.ASCII.GetString(m_Reader.ReadBytes(strLength));
            return str;
        }

        /// <summary>
        /// Reads a list of floats from the message. The length of the list is stored in the message.
        /// </summary>
        /// <param name="defaultValue">Default value to use if the end of the message is reached.</param>
        /// <returns></returns>
        public IList<float> ReadFloatList(IList<float> defaultValue = default)
        {
            if (!CanReadMore())
            {
                return defaultValue;
            }

            var len = ReadInt32();
            var output = new float[len];
            for (var i = 0; i < len; i++)
            {
                output[i] = ReadFloat32();
            }

            return output;
        }

        /// <summary>
        /// Gets the original data of the message. Note that this will return all of the data,
        /// even if part of it has already been read.
        /// </summary>
        /// <returns></returns>
        public byte[] GetRawBytes()
        {
            return m_Data;
        }

        /// <summary>
        /// Clean up the internal storage.
        /// </summary>
        public void Dispose()
        {
            m_Reader?.Dispose();
            m_Stream?.Dispose();
        }

        /// <summary>
        /// Whether or not there is more data left in the stream that can be read.
        /// </summary>
        /// <returns></returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        bool CanReadMore()
        {
            return m_Stream.Position < m_Stream.Length;
        }
    }
}