1: <?php declare( strict_types = 1 );
2:
3: namespace Waves\Transactions\Invocation;
4:
5: use Exception;
6: use Waves\Common\Base64String;
7: use Waves\Common\ExceptionCode;
8: use Waves\Common\Json;
9: use Waves\Common\Value;
10:
11: class Arg
12: {
13: const BINARY = 1;
14: const BOOLEAN = 2;
15: const INTEGER = 3;
16: const STRING = 4;
17: const LIST = 5;
18:
19: private int $type;
20: private Value $value;
21:
22: static function as( int $type, Value $value ): Arg
23: {
24: $arg = new Arg;
25: $arg->type = $type;
26: $arg->value = $value;
27: return $arg;
28: }
29:
30: static function fromJson( Json $json ): Arg
31: {
32: $type = Arg::stringToType( $json->get( 'type' )->asString() );
33: if( $type === Arg::LIST )
34: {
35: $args = [];
36: foreach( $json->get( 'value' )->asArray() as $arg )
37: $args[] = Arg::fromJson( Value::as( $arg )->asJson() );
38: $value = Value::as( $args );
39: }
40: else
41: if( $type === Arg::BINARY )
42: {
43: $value = Value::as( $json->get( 'value' )->asBase64Decoded() );
44: }
45: else
46: {
47: $value = $json->get( 'value' );
48: }
49:
50: return Arg::as( $type, $value );
51: }
52:
53: static function stringToType( string $stringType ): int
54: {
55: switch( $stringType )
56: {
57: case 'binary': return Arg::BINARY;
58: case 'boolean': return Arg::BOOLEAN;
59: case 'integer': return Arg::INTEGER;
60: case 'string': return Arg::STRING;
61: case 'list': return Arg::LIST;
62: default: throw new Exception( __FUNCTION__ . ' failed to detect type `' . serialize( $stringType ) . '`', ExceptionCode::UNKNOWN_TYPE );
63: }
64: }
65:
66: static function typeToString( int $type ): string
67: {
68: switch( $type )
69: {
70: case Arg::BINARY: return 'binary';
71: case Arg::BOOLEAN: return 'boolean';
72: case Arg::INTEGER: return 'integer';
73: case Arg::STRING: return 'string';
74: case Arg::LIST: return 'list';
75: default: throw new Exception( __FUNCTION__ . ' failed to detect type `' . serialize( $type ) . '`', ExceptionCode::UNKNOWN_TYPE );
76: }
77: }
78:
79: function type(): int
80: {
81: return $this->type;
82: }
83:
84: function typeAsString(): string
85: {
86: return Arg::typeToString( $this->type() );
87: }
88:
89: function value(): Value
90: {
91: return $this->value;
92: }
93:
94: /**
95: * @return mixed
96: */
97: private function valueAsJson()
98: {
99: switch( $this->type() )
100: {
101: case Arg::BINARY: return Base64String::fromBytes( $this->value()->asString() )->encodedWithPrefix();
102: case Arg::BOOLEAN: return $this->value()->asBoolean();
103: case Arg::INTEGER: return $this->value()->asInt();
104: case Arg::STRING: return $this->value()->asString();
105: case Arg::LIST:
106: {
107: $values = [];
108: foreach( $this->value()->asArray() as $arg )
109: {
110: if( !( $arg instanceof Arg ) )
111: throw new Exception( __FUNCTION__ . ' failed to detect Arg class', ExceptionCode::UNEXPECTED );
112: $values[] = $arg->toJsonValue();
113: }
114: return $values;
115: }
116: default: throw new Exception( __FUNCTION__ . ' failed to detect type `' . serialize( $this->type() ) . '`', ExceptionCode::UNKNOWN_TYPE );
117: }
118: }
119:
120: /**
121: * @return array<string, mixed>
122: */
123: function toJsonValue(): array
124: {
125: return [ 'type' => $this->typeAsString(), 'value' => $this->valueAsJson() ];
126: }
127: }
128: