blob: 22f17423bc400958e862dd51cb272d192576d97b [file] [log] [blame]
<?php
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package thrift.protocol
*/
namespace Thrift\Protocol;
use Thrift\Exception\TException;
use Thrift\Exception\TProtocolException;
use Thrift\Protocol\SimpleJSON\Context;
use Thrift\Protocol\SimpleJSON\ListContext;
use Thrift\Protocol\SimpleJSON\StructContext;
use Thrift\Protocol\SimpleJSON\MapContext;
use Thrift\Protocol\SimpleJSON\CollectionMapKeyException;
/**
* SimpleJSON implementation of thrift protocol, ported from Java.
*/
class TSimpleJSONProtocol extends TProtocol
{
const COMMA = ',';
const COLON = ':';
const LBRACE = '{';
const RBRACE = '}';
const LBRACKET = '[';
const RBRACKET = ']';
const QUOTE = '"';
const NAME_MAP = "map";
const NAME_LIST = "lst";
const NAME_SET = "set";
protected $writeContext_ = null;
protected $writeContextStack_ = [];
/**
* Push a new write context onto the stack.
*/
protected function pushWriteContext(Context $c)
{
$this->writeContextStack_[] = $this->writeContext_;
$this->writeContext_ = $c;
}
/**
* Pop the last write context off the stack
*/
protected function popWriteContext()
{
$this->writeContext_ = array_pop($this->writeContextStack_);
}
/**
* Used to make sure that we are not encountering a map whose keys are containers
*/
protected function assertContextIsNotMapKey($invalidKeyType)
{
if ($this->writeContext_->isMapKey()) {
throw new CollectionMapKeyException(
"Cannot serialize a map with keys that are of type " .
$invalidKeyType
);
}
}
private function writeJSONString($b)
{
$this->writeContext_->write();
$this->trans_->write(json_encode((string)$b));
}
private function writeJSONInteger($num)
{
$isMapKey = $this->writeContext_->isMapKey();
$this->writeContext_->write();
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
$this->trans_->write((int)$num);
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
}
private function writeJSONDouble($num)
{
$isMapKey = $this->writeContext_->isMapKey();
$this->writeContext_->write();
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
#TODO add compatibility with NAN and INF
$this->trans_->write(json_encode((float)$num));
if ($isMapKey) {
$this->trans_->write(self::QUOTE);
}
}
/**
* Constructor
*/
public function __construct($trans)
{
parent::__construct($trans);
$this->writeContext_ = new Context();
}
/**
* Writes the message header
*
* @param string $name Function name
* @param int $type message type TMessageType::CALL or TMessageType::REPLY
* @param int $seqid The sequence id of this message
*/
public function writeMessageBegin($name, $type, $seqid)
{
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
$this->writeJSONString($name);
$this->writeJSONInteger($type);
$this->writeJSONInteger($seqid);
}
/**
* Close the message
*/
public function writeMessageEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
/**
* Writes a struct header.
*
* @param string $name Struct name
*/
public function writeStructBegin($name)
{
$this->writeContext_->write();
$this->trans_->write(self::LBRACE);
$this->pushWriteContext(new StructContext($this));
}
/**
* Close a struct.
*/
public function writeStructEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACE);
}
public function writeFieldBegin($fieldName, $fieldType, $fieldId)
{
$this->writeJSONString($fieldName);
}
public function writeFieldEnd()
{
}
public function writeFieldStop()
{
}
public function writeMapBegin($keyType, $valType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_MAP);
$this->writeContext_->write();
$this->trans_->write(self::LBRACE);
$this->pushWriteContext(new MapContext($this));
}
public function writeMapEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACE);
}
public function writeListBegin($elemType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_LIST);
$this->writeContext_->write();
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
// No metadata!
}
public function writeListEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
public function writeSetBegin($elemType, $size)
{
$this->assertContextIsNotMapKey(self::NAME_SET);
$this->writeContext_->write();
$this->trans_->write(self::LBRACKET);
$this->pushWriteContext(new ListContext($this));
// No metadata!
}
public function writeSetEnd()
{
$this->popWriteContext();
$this->trans_->write(self::RBRACKET);
}
public function writeBool($bool)
{
$this->writeJSONInteger($bool ? 1 : 0);
}
public function writeByte($byte)
{
$this->writeJSONInteger($byte);
}
public function writeI16($i16)
{
$this->writeJSONInteger($i16);
}
public function writeI32($i32)
{
$this->writeJSONInteger($i32);
}
public function writeI64($i64)
{
$this->writeJSONInteger($i64);
}
public function writeDouble($dub)
{
$this->writeJSONDouble($dub);
}
public function writeString($str)
{
$this->writeJSONString($str);
}
/**
* Reading methods.
*
* simplejson is not meant to be read back into thrift
* - see http://wiki.apache.org/thrift/ThriftUsageJava
* - use JSON instead
*/
public function readMessageBegin(&$name, &$type, &$seqid)
{
throw new TException("Not implemented");
}
public function readMessageEnd()
{
throw new TException("Not implemented");
}
public function readStructBegin(&$name)
{
throw new TException("Not implemented");
}
public function readStructEnd()
{
throw new TException("Not implemented");
}
public function readFieldBegin(&$name, &$fieldType, &$fieldId)
{
throw new TException("Not implemented");
}
public function readFieldEnd()
{
throw new TException("Not implemented");
}
public function readMapBegin(&$keyType, &$valType, &$size)
{
throw new TException("Not implemented");
}
public function readMapEnd()
{
throw new TException("Not implemented");
}
public function readListBegin(&$elemType, &$size)
{
throw new TException("Not implemented");
}
public function readListEnd()
{
throw new TException("Not implemented");
}
public function readSetBegin(&$elemType, &$size)
{
throw new TException("Not implemented");
}
public function readSetEnd()
{
throw new TException("Not implemented");
}
public function readBool(&$bool)
{
throw new TException("Not implemented");
}
public function readByte(&$byte)
{
throw new TException("Not implemented");
}
public function readI16(&$i16)
{
throw new TException("Not implemented");
}
public function readI32(&$i32)
{
throw new TException("Not implemented");
}
public function readI64(&$i64)
{
throw new TException("Not implemented");
}
public function readDouble(&$dub)
{
throw new TException("Not implemented");
}
public function readString(&$str)
{
throw new TException("Not implemented");
}
}