2016-03-16 14:25:35 -04:00
|
|
|
// Copyright 2016 Matthew Collins
|
2015-09-17 11:21:56 -04:00
|
|
|
//
|
|
|
|
// Licensed 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.
|
2015-09-12 15:31:26 -04:00
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
use std::io;
|
|
|
|
use std::fmt;
|
2018-11-04 14:48:03 -05:00
|
|
|
use crate::protocol;
|
|
|
|
use crate::protocol::Serializable;
|
|
|
|
use crate::format;
|
|
|
|
use crate::item;
|
|
|
|
use crate::shared::Position;
|
2015-09-12 15:31:26 -04:00
|
|
|
|
|
|
|
pub struct MetadataKey<T: MetaValue> {
|
|
|
|
index: i32,
|
|
|
|
ty: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <T: MetaValue> MetadataKey<T> {
|
2015-09-17 11:04:25 -04:00
|
|
|
#[allow(dead_code)]
|
2018-11-02 19:57:23 -04:00
|
|
|
fn new(index: i32) -> MetadataKey<T> {
|
2015-09-12 15:31:26 -04:00
|
|
|
MetadataKey {
|
2018-11-04 16:43:30 -05:00
|
|
|
index,
|
2015-09-12 15:31:26 -04:00
|
|
|
ty: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Metadata {
|
|
|
|
map: HashMap<i32, Value>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Metadata {
|
|
|
|
pub fn new() -> Metadata {
|
|
|
|
Metadata { map: HashMap::new() }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get<T: MetaValue>(&self, key: &MetadataKey<T>) -> Option<&T> {
|
|
|
|
self.map.get(&key.index).map(T::unwrap)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn put<T: MetaValue>(&mut self, key: &MetadataKey<T>, val: T) {
|
|
|
|
self.map.insert(key.index, val.wrap());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn put_raw<T: MetaValue>(&mut self, index: i32, val: T) {
|
|
|
|
self.map.insert(index, val.wrap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Serializable for Metadata {
|
|
|
|
|
2016-04-08 13:46:07 -04:00
|
|
|
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, protocol::Error> {
|
2015-09-12 15:31:26 -04:00
|
|
|
let mut m = Metadata::new();
|
|
|
|
loop {
|
2018-11-04 14:34:53 -05:00
|
|
|
let index = u8::read_from(buf)? as i32;
|
2015-09-12 15:31:26 -04:00
|
|
|
if index == 0xFF {
|
|
|
|
break;
|
|
|
|
}
|
2018-11-04 14:34:53 -05:00
|
|
|
let ty = u8::read_from(buf)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
match ty {
|
2018-11-04 14:34:53 -05:00
|
|
|
0 => m.put_raw(index, i8::read_from(buf)?),
|
|
|
|
1 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0),
|
|
|
|
2 => m.put_raw(index, f32::read_from(buf)?),
|
|
|
|
3 => m.put_raw(index, String::read_from(buf)?),
|
|
|
|
4 => m.put_raw(index, format::Component::read_from(buf)?),
|
|
|
|
5 => m.put_raw(index, Option::<item::Stack>::read_from(buf)?),
|
|
|
|
6 => m.put_raw(index, bool::read_from(buf)?),
|
2015-10-07 14:36:59 -04:00
|
|
|
7 => m.put_raw(index,
|
2018-11-04 14:34:53 -05:00
|
|
|
[f32::read_from(buf)?,
|
|
|
|
f32::read_from(buf)?,
|
|
|
|
f32::read_from(buf)?]),
|
|
|
|
8 => m.put_raw(index, Position::read_from(buf)?),
|
2015-09-12 15:31:26 -04:00
|
|
|
9 => {
|
2018-11-04 14:34:53 -05:00
|
|
|
if bool::read_from(buf)? {
|
|
|
|
m.put_raw(index, Option::<Position>::read_from(buf)?);
|
2015-09-12 15:31:26 -04:00
|
|
|
} else {
|
2016-04-03 15:53:40 -04:00
|
|
|
m.put_raw::<Option<Position>>(index, None);
|
2015-09-12 15:31:26 -04:00
|
|
|
}
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2018-11-04 14:34:53 -05:00
|
|
|
10 => m.put_raw(index, protocol::VarInt::read_from(buf)?),
|
2015-09-12 15:31:26 -04:00
|
|
|
11 => {
|
2018-11-04 14:34:53 -05:00
|
|
|
if bool::read_from(buf)? {
|
|
|
|
m.put_raw(index, Option::<protocol::UUID>::read_from(buf)?);
|
2015-09-12 15:31:26 -04:00
|
|
|
} else {
|
|
|
|
m.put_raw::<Option<protocol::UUID>>(index, None);
|
|
|
|
}
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2018-11-04 14:34:53 -05:00
|
|
|
12 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0 as u16),
|
2016-04-08 13:46:07 -04:00
|
|
|
_ => return Err(protocol::Error::Err("unknown metadata type".to_owned())),
|
2015-09-12 15:31:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(m)
|
|
|
|
}
|
|
|
|
|
2016-04-08 13:46:07 -04:00
|
|
|
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), protocol::Error> {
|
2015-09-12 15:31:26 -04:00
|
|
|
for (k, v) in &self.map {
|
2018-11-04 14:34:53 -05:00
|
|
|
(*k as u8).write_to(buf)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
match *v {
|
|
|
|
Value::Byte(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&0, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Int(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&1, buf)?;
|
|
|
|
protocol::VarInt(*val).write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Float(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&2, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::String(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&3, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::FormatComponent(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&4, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::OptionalItemStack(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&5, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Bool(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&6, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Vector(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&7, buf)?;
|
|
|
|
val[0].write_to(buf)?;
|
|
|
|
val[1].write_to(buf)?;
|
|
|
|
val[2].write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Position(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&8, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::OptionalPosition(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&9, buf)?;
|
|
|
|
val.is_some().write_to(buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Direction(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&10, buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
}
|
|
|
|
Value::OptionalUUID(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&11, buf)?;
|
|
|
|
val.is_some().write_to(buf)?;
|
|
|
|
val.write_to(buf)?;
|
2015-10-07 14:36:59 -04:00
|
|
|
}
|
2015-09-12 15:31:26 -04:00
|
|
|
Value::Block(ref val) => {
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&11, buf)?;
|
|
|
|
protocol::VarInt(*val as i32).write_to(buf)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-04 14:34:53 -05:00
|
|
|
u8::write_to(&0xFF, buf)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for Metadata {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2018-11-04 14:34:53 -05:00
|
|
|
write!(f, "Metadata[ ")?;
|
2015-09-12 15:31:26 -04:00
|
|
|
for (k, v) in &self.map {
|
2018-11-04 14:34:53 -05:00
|
|
|
write!(f, "{:?}={:?}, ", k, v)?;
|
2015-09-12 15:31:26 -04:00
|
|
|
}
|
|
|
|
write!(f, "]")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Metadata {
|
|
|
|
fn default() -> Metadata {
|
|
|
|
Metadata::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
2016-03-16 14:01:33 -04:00
|
|
|
pub enum Value {
|
2015-09-12 15:31:26 -04:00
|
|
|
Byte(i8),
|
|
|
|
Int(i32),
|
|
|
|
Float(f32),
|
|
|
|
String(String),
|
|
|
|
FormatComponent(format::Component),
|
|
|
|
OptionalItemStack(Option<item::Stack>),
|
|
|
|
Bool(bool),
|
|
|
|
Vector([f32; 3]),
|
2016-04-03 15:53:40 -04:00
|
|
|
Position(Position),
|
|
|
|
OptionalPosition(Option<Position>),
|
2015-09-12 15:31:26 -04:00
|
|
|
Direction(protocol::VarInt), // TODO: Proper type
|
|
|
|
OptionalUUID(Option<protocol::UUID>),
|
|
|
|
Block(u16), // TODO: Proper type
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait MetaValue {
|
2018-11-04 14:33:23 -05:00
|
|
|
fn unwrap(_: &Value) -> &Self;
|
2015-09-12 15:31:26 -04:00
|
|
|
fn wrap(self) -> Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for i8 {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Byte(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Byte(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for i32 {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Int(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Int(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for f32 {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Float(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Float(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for String {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::String(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::String(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for format::Component {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::FormatComponent(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::FormatComponent(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for Option<item::Stack> {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::OptionalItemStack(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::OptionalItemStack(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for bool {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Bool(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Bool(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for [f32; 3] {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Vector(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Vector(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-03 15:53:40 -04:00
|
|
|
impl MetaValue for Position {
|
2015-09-12 15:31:26 -04:00
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Position(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Position(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-03 15:53:40 -04:00
|
|
|
impl MetaValue for Option<Position> {
|
2015-09-12 15:31:26 -04:00
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::OptionalPosition(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::OptionalPosition(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for protocol::VarInt {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Direction(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Direction(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for Option<protocol::UUID> {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::OptionalUUID(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::OptionalUUID(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetaValue for u16 {
|
|
|
|
fn unwrap(value: &Value) -> &Self {
|
|
|
|
match *value {
|
|
|
|
Value::Block(ref val) => val,
|
|
|
|
_ => panic!("incorrect key"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn wrap(self) -> Value {
|
|
|
|
Value::Block(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
const TEST: MetadataKey<String> =
|
|
|
|
MetadataKey {
|
2015-10-07 14:36:59 -04:00
|
|
|
index: 0,
|
|
|
|
ty: PhantomData,
|
|
|
|
};
|
2015-09-12 15:31:26 -04:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn basic() {
|
|
|
|
let mut m = Metadata::new();
|
|
|
|
|
|
|
|
m.put(&TEST, "Hello world".to_owned());
|
|
|
|
|
|
|
|
match m.get(&TEST) {
|
|
|
|
Some(val) => {
|
|
|
|
assert!(val == "Hello world");
|
|
|
|
}
|
|
|
|
None => panic!("failed"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|