Skip to content

Commit

Permalink
Implement string conversions for Int and Float
Browse files Browse the repository at this point in the history
  • Loading branch information
fuerstenau committed Dec 9, 2018
1 parent 273739e commit 09c33cc
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 27 deletions.
76 changes: 60 additions & 16 deletions src/data.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use super::Byte;
use super::Input;
use nom::InputIter;
use std::str::FromStr;
use std::string::ToString;
//use super::MessagePart;
struct MessagePart {
data: Vec<Byte>,
msg: Vec<Byte>,
}

// TODO: I'm unhappy with quite a few of the names.
Expand Down Expand Up @@ -42,8 +44,21 @@ mod simple_entity {
Boolean(super::Boolean),
}

pub trait SimpleEntity: Data + TryFrom<Value> + Into<Value> {
pub trait SimpleEntity: Data + TryFrom<Value> + Into<Value> {}
}

// TODO: Get this to namespace sensibly.
mod data_types {
macro_rules! singleton_type {
( $i: ident ) => {
pub enum $i {
$i,
}
};
}

singleton_type!(Int);
singleton_type!(Float);
}

pub trait GtpType {}
Expand All @@ -58,28 +73,29 @@ pub struct Int {
}

impl From<Int> for MessagePart {
fn from(Int{ data }: Int) -> MessagePart {
let data = Vec::new();
MessagePart { data }
fn from(Int { data }: Int) -> MessagePart {
let msg = Vec::from(data.to_string().as_bytes());
MessagePart { msg }
}
}

// TODO: Get tihs to namespace sensibly.
mod data_types {
macro_rules! singleton_type {
( $i: ident ) => {pub enum $i { $i, }}
}

singleton_type!(Int);
}

impl Data for Int {
type Type = data_types::Int;

// FIXME: Error handling
fn parse(i: Input, _t: Self::Type) -> IResult<Input, Self> {
let data = map!(i, nom::digit, |str| FromStr::from_str(&str).unwrap());
Ok(Int { data })
let digits = nom::digit(i);
match digits {
Ok((rem, str)) => {
let str = str
.iter_elements()
.map(nom::AsChar::as_char)
.collect::<std::string::String>();
let data = FromStr::from_str(&str).unwrap();
Ok((rem, Int { data }))
}
Err(e) => Err(e),
}
}

fn typed(&self) -> Self::Type {
Expand All @@ -93,6 +109,34 @@ pub struct Float {
data: f32,
}

impl From<Float> for MessagePart {
fn from(Float { data }: Float) -> MessagePart {
let msg = Vec::from(data.to_string().as_bytes());
MessagePart { msg }
}
}

impl Data for Float {
type Type = data_types::Float;

/// The GTP “specification” does not specify
/// in which ways a float may be represented.
/// We therefore simply accept as a float
/// whatever nom accepts as a float.
// FIXME: Error handling
fn parse(i: Input, _t: Self::Type) -> IResult<Input, Self> {
let result = nom::float(i);
match result {
Ok((rem, data)) => Ok((rem, Float { data })),
Err(e) => Err(e),
}
}

fn typed(&self) -> Self::Type {
data_types::Float::Float
}
}

impl SimpleEntity for Float {}

pub struct String {
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ mod parse;
use messages::MessagePart;
use parse::Input;


mod messages {
pub struct MessagePart {
data: Vec<Byte>,
Expand Down
48 changes: 38 additions & 10 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use nom::*;
use std::iter;

const DISCARD: [Byte; 31] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127,
0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 127,
]; // “Control characters”: 0 – 8, 11 – 31, 127
const SPACE: [Byte; 2] = [9, 32]; // " \t"
const NEWLINE: Byte = 10; // "\n"
const COMMENT: Byte = 35; // "#"

#[derive(Clone, Copy)]
pub struct Input<'a> {
bytes: &'a [Byte],
}
Expand All @@ -23,8 +24,8 @@ impl<'a> std::convert::From<&'a [u8]> for Input<'a> {
impl<'a> AtEof for Input<'a> {
/// While it might be possible in some settings
/// to determine that the connection has closed
/// and no further data may arrive
/// it is quite considering the particular syntax of GTP.
/// and no further data may arrive,
/// it is quite irrelevant considering the particular syntax of GTP.
/// The only use case would be determining malformed input
/// which ends without proper termination
/// but this is currently beyond the scope
Expand Down Expand Up @@ -54,10 +55,37 @@ impl<'a> InputTake for Input<'a> {
}
}

impl<'a, R> Slice<R> for Input<'a>
where
&'a [Byte]: Slice<R>,
{
fn slice(&self, range: R) -> Self {
let bytes = self.bytes.slice(range);
Input { bytes }
}
}

impl<'a> Offset for Input<'a> {
fn offset(&self, second: &Self) -> usize {
self.bytes.offset(second.bytes)
}
}

impl<'a, R> ParseTo<R> for Input<'a>
where
&'a [Byte]: ParseTo<R>,
{
fn parse_to(&self) -> Option<R> {
self.bytes.parse_to()
}
}

/// This allows us to use a default implementation for InputTakeAtPosition.
impl<'a> UnspecializedInput for Input<'a> {}

pub struct InputIterator<'a> {
bytes: &'a [Byte],
/// One more than the position of the last element
/// that was output.
/// One more than the position of the last element that was output.
/// If we are not at the end of the iteration
/// and there are no discardable bytes,
/// it happens to be the position of the next element.
Expand Down Expand Up @@ -109,18 +137,18 @@ impl<'a> InputIter for Input<'a> {

fn position<P>(&self, predicate: P) -> Option<usize>
where
P: Fn(Self::RawItem) -> bool
P: Fn(Self::RawItem) -> bool,
{
let mut iter = self.iter_elements();
loop {
if let Some(elem) = iter.next() {
if predicate(elem) {
continue
continue;
} else {
break Some(iter.last_pos())
break Some(iter.last_pos());
}
} else {
break None
break None;
}
}
}
Expand Down

0 comments on commit 09c33cc

Please sign in to comment.