blob: 18aa4f75ba8006036e7fd837025c7b0c9e50929f [file] [log] [blame]
//
// Copyright (c) 2010-2024 Antmicro
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Antmicro.Renode.Debugging;
using Antmicro.Renode.Utilities;
namespace Antmicro.Renode.Network.ExternalControl
{
public class Response
{
public static Response CommandFailed(Command command, string reason)
{
return new Response(ReturnCode.CommandFailed, command, text: reason);
}
public static Response FatalError(string reason)
{
return new Response(ReturnCode.FatalError, text: reason);
}
public static Response InvalidCommand(Command command)
{
return new Response(ReturnCode.InvalidCommand, command);
}
public static Response Success(Command command)
{
return new Response(ReturnCode.SuccessWithoutData, command);
}
public static Response Success(Command command, IEnumerable<byte> data)
{
return new Response(ReturnCode.SuccessWithData, command, data);
}
public static Response Success(Command command, string text)
{
return new Response(ReturnCode.SuccessWithData, command, text);
}
public static Response SuccessfulHandshake()
{
return new Response(ReturnCode.SuccessfulHandshake);
}
private Response(ReturnCode returnCode)
: this(returnCode, null, (byte[])null)
{
}
private Response(ReturnCode returnCode, string text)
: this(returnCode, null, text)
{
}
private Response(ReturnCode returnCode, Command? command, string text)
: this(returnCode, command, Encoding.ASCII.GetBytes(text))
{
dataIsText = true;
}
private Response(ReturnCode returnCode, Command? command, IEnumerable<byte> data)
: this(returnCode, command, data.ToArray())
{
}
private Response(ReturnCode returnCode, Command? command, byte[] data = null)
{
// Command can be null only for FatalError and SuccessfulHandshake
DebugHelper.Assert(command != null || returnCode == ReturnCode.FatalError || returnCode == ReturnCode.SuccessfulHandshake);
this.returnCode = returnCode;
this.command = command;
this.data = data;
dataIsText = false;
}
public IEnumerable<byte> GetBytes()
{
var response = new List<byte> { (byte)returnCode };
if(command.HasValue)
{
response.Add((byte)command);
}
if(data != null && data.Any())
{
response.AddRange(checked((uint)data.Length).AsRawBytes());
response.AddRange(data);
}
return response;
}
public override string ToString()
{
var result = new StringBuilder("Response(")
.Append(returnCode);
if(command.HasValue)
{
result
.Append(", command: ")
.Append(command);
}
if(data != null)
{
result
.Append(", data: ")
.Append(dataIsText ? Encoding.ASCII.GetString(data) : Misc.PrettyPrintCollectionHex(data));
}
return result
.Append(')')
.ToString();
}
private readonly bool dataIsText;
private readonly Command? command;
private readonly byte[] data;
private readonly ReturnCode returnCode;
// matches the return_code_t enum in tools/external_control_client/lib/renode_api.c
private enum ReturnCode : byte
{
CommandFailed,
FatalError,
InvalidCommand,
SuccessWithData,
SuccessWithoutData,
SuccessfulHandshake,
}
}
}