88use Fbns \Thrift \Map ;
99use Fbns \Thrift \Series ;
1010use Fbns \Thrift \Struct ;
11- use SplStack ;
1211
1312/**
1413 * WARNING: This implementation is not complete.
1716 */
1817class Reader
1918{
20- /** @var SplStack */
21- private $ stack ;
22-
23- /** @var int */
24- private $ field ;
25-
2619 /** @var ReadBuffer */
2720 private $ buffer ;
2821
29- public function __construct (string $ buffer = '' )
22+ public function __construct (string $ buffer )
3023 {
31- $ this ->stack = new SplStack ();
3224 $ this ->buffer = new ReadBuffer ($ buffer );
3325 }
3426
3527 public function __invoke (): Struct
3628 {
3729 $ this ->buffer ->rewind ();
38- $ this ->field = 0 ;
39- while (!$ this ->stack ->isEmpty ()) {
40- $ this ->stack ->pop ();
41- }
4230
43- return new Struct ($ this ->readStruct ());
31+ return $ this ->readStruct ();
32+ }
33+
34+ private function readStruct (): Struct
35+ {
36+ return new Struct ($ this ->readStructFields ());
4437 }
4538
46- private function readStruct (): \Generator
39+ private function readStructFields (): \Generator
4740 {
48- while ($ this ->buffer ->isEmpty ()) {
49- $ type = $ this ->readField ();
41+ $ field = 0 ;
42+ while (!$ this ->buffer ->isEmpty ()) {
43+ [$ field , $ type ] = $ this ->readNextField ($ field );
5044 switch ($ type ) {
51- case Types::STRUCT :
52- $ field = $ this ->field ;
53- $ this ->stack ->push ($ this ->field );
54- $ this ->field = 0 ;
55- yield $ field => new Struct ($ this ->readStruct ());
56- break ;
5745 case Types::STOP :
58- if (!$ this ->stack ->isEmpty ()) {
59- $ this ->field = $ this ->stack ->pop ();
60- }
61-
6246 return ;
63- case Types::LIST :
64- $ sizeAndType = $ this ->buffer ->readUnsignedByte ();
65- $ size = $ sizeAndType >> 4 ;
66- $ listType = $ sizeAndType & 0x0f ;
67- if ($ size === 0x0f ) {
68- $ size = $ this ->buffer ->readVarint ();
69- }
70- yield $ this ->field => new Series ($ listType , $ this ->readList ($ size , $ listType ));
71- break ;
7247 case Types::TRUE :
7348 case Types::FALSE :
74- yield $ this ->field => new Field ($ type , $ type === Types::TRUE );
75- break ;
76- case Types::BYTE :
77- yield $ this ->field => new Field ($ type , $ this ->buffer ->readSignedByte ());
78- break ;
79- case Types::I16 :
80- case Types::I32 :
81- case Types::I64 :
82- yield $ this ->field => new Field ($ type , $ this ->fromZigZag ($ this ->buffer ->readVarint ()));
83- break ;
84- case Types::BINARY :
85- yield $ this ->field => new Field ($ type , $ this ->buffer ->readString ($ this ->buffer ->readVarint ()));
86- break ;
87- case Types::MAP :
88- $ size = $ this ->buffer ->readVarint ();
89- $ types = $ this ->buffer ->readUnsignedByte ();
90- $ keyType = $ types >> 4 ;
91- $ valueType = $ types & 0x0f ;
92- yield $ this ->field => new Map ($ keyType , $ valueType , $ this ->readMap ($ size , $ keyType , $ valueType ));
49+ // Boolean fields are inlined, so there is no need to read them.
50+ yield $ field => new Field (Types::TRUE , $ type === Types::TRUE );
9351 break ;
9452 default :
95- throw new \ DomainException ( " Unsupported field type { $ type} . " );
53+ yield $ field => $ this -> readWrappedValue ( $ type );
9654 }
9755 }
9856 }
9957
100- private function readField ( ): int
58+ private function readNextField ( int $ currentField ): array
10159 {
10260 $ typeAndDelta = $ this ->buffer ->readUnsignedByte ();
10361 if ($ typeAndDelta === Types::STOP ) {
104- return Types::STOP ;
62+ return [ $ currentField , Types::STOP ] ;
10563 }
10664 $ delta = $ typeAndDelta >> 4 ;
65+ $ nextField = $ currentField ;
10766 if ($ delta === 0 ) {
108- $ this -> field = $ this ->fromZigZag ($ this ->buffer ->readVarint ());
67+ $ nextField = $ this ->fromZigZag ($ this ->buffer ->readVarint ());
10968 } else {
110- $ this -> field += $ delta ;
69+ $ nextField += $ delta ;
11170 }
11271 $ type = $ typeAndDelta & 0x0f ;
11372
114- return $ type ;
73+ return [ $ nextField , $ type] ;
11574 }
11675
117- private function readList (int $ size , int $ type ): \Generator
76+ private function readList (): Series
77+ {
78+ $ sizeAndType = $ this ->buffer ->readUnsignedByte ();
79+ $ size = $ sizeAndType >> 4 ;
80+ $ listType = $ sizeAndType & 0x0f ;
81+ if ($ size === 0x0f ) {
82+ $ size = $ this ->buffer ->readVarint ();
83+ }
84+
85+ return new Series ($ listType , $ this ->readListItems ($ size , $ listType ));
86+ }
87+
88+ private function readListItems (int $ size , int $ type ): \Generator
11889 {
11990 for ($ i = 0 ; $ i < $ size ; $ i ++) {
120- yield $ this ->readPrimitive ($ type );
91+ yield $ this ->readValue ($ type );
12192 }
12293 }
12394
95+ private function readMap (): Map
96+ {
97+ $ size = $ this ->buffer ->readVarint ();
98+ $ types = $ this ->buffer ->readUnsignedByte ();
99+ $ keyType = $ types >> 4 ;
100+ $ valueType = $ types & 0x0f ;
101+
102+ return new Map ($ keyType , $ valueType , $ this ->readMapItems ($ size , $ keyType , $ valueType ));
103+ }
104+
105+ private function readMapItems (int $ size , int $ keyType , int $ valueType ): \Generator
106+ {
107+ for ($ i = 0 ; $ i < $ size ; $ i ++) {
108+ yield $ this ->readValue ($ keyType ) => $ this ->readValue ($ valueType );
109+ }
110+ }
111+
112+ private function readWrappedValue (int $ type ): Field
113+ {
114+ $ result = $ this ->readValue ($ type );
115+ if ($ result instanceof Field) {
116+ return $ result ;
117+ }
118+
119+ return new Field ($ type , $ result );
120+ }
121+
124122 /**
125123 * @return mixed
126124 */
127- private function readPrimitive (int $ type )
125+ private function readValue (int $ type )
128126 {
129127 switch ($ type ) {
128+ case Types::STRUCT :
129+ return $ this ->readStruct ();
130+ case Types::LIST :
131+ return $ this ->readList ();
132+ case Types::MAP :
133+ return $ this ->readMap ();
130134 case Types::TRUE :
131135 case Types::FALSE :
132136 return $ this ->buffer ->readSignedByte () === Types::TRUE ;
@@ -139,14 +143,7 @@ private function readPrimitive(int $type)
139143 case Types::BINARY :
140144 return $ this ->buffer ->readString ($ this ->buffer ->readVarint ());
141145 default :
142- throw new \DomainException ("Unsupported primitive type {$ type }. " );
143- }
144- }
145-
146- private function readMap (int $ size , int $ keyType , int $ valueType ): \Generator
147- {
148- for ($ i = 0 ; $ i < $ size ; $ i ++) {
149- yield $ this ->readPrimitive ($ keyType ) => $ this ->readPrimitive ($ valueType );
146+ throw new \DomainException ("Unsupported type {$ type }. " );
150147 }
151148 }
152149
0 commit comments