<commit_before>pub struct PLPWriter
{
	pub use_tabs: bool,
	pub indent_level: u16,
	pub code: String,
}

impl PLPWriter
{
	// TODO: implement indentation writing
	pub fn new() -> PLPWriter
	{
		PLPWriter {
			use_tabs: true,
			indent_level: 0,
			code: String::new(),
			}
	}

	pub fn reset(&mut self)
	{
		self.indent_level = 0;
		self.code = String::new();
	}

	pub fn li(&mut self, register: &str, value: &str) -> String
	{
		let mut code = String::new();
		code.push_str("li ");
		code.push_str(register);
		code.push_str(", ");
		code.push_str(value);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mov(&mut self, register_to: &str, register_from: &str) -> String
	{
		let mut code = String::new();
		code.push_str("move ");
		code.push_str(register_to);
		code.push_str(", ");
		code.push_str(register_from);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn addu(&mut self, register_sum: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("addu ");
		code.push_str(register_sum);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn subu(&mut self, register_difference: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_difference);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mullo(&mut self, register_product: &str, register_multiplicand1: &str, register_multiplicand2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_product);
		code.push_str(", ");
		code.push_str(register_multiplicand1);
		code.push_str(", ");
		code.push_str(register_multiplicand2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn sw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("sw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn lw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("lw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn push(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("push ");
		code.push_str(register_target);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn pop(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("pop ");
		code.push_str(register_target);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}
}
<commit_msg>Add support for call and nop functions<commit_after>pub struct PLPWriter
{
	pub use_tabs: bool,
	pub indent_level: u16,
	pub code: String,
}

impl PLPWriter
{
	// TODO: implement indentation writing
	pub fn new() -> PLPWriter
	{
		PLPWriter {
			use_tabs: true,
			indent_level: 0,
			code: String::new(),
			}
	}

	pub fn reset(&mut self)
	{
		self.indent_level = 0;
		self.code = String::new();
	}

	pub fn li(&mut self, register: &str, value: &str) -> String
	{
		let mut code = String::new();
		code.push_str("li ");
		code.push_str(register);
		code.push_str(", ");
		code.push_str(value);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mov(&mut self, register_to: &str, register_from: &str) -> String
	{
		let mut code = String::new();
		code.push_str("move ");
		code.push_str(register_to);
		code.push_str(", ");
		code.push_str(register_from);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn addu(&mut self, register_sum: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("addu ");
		code.push_str(register_sum);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn subu(&mut self, register_difference: &str, register_addend1: &str, register_addend2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_difference);
		code.push_str(", ");
		code.push_str(register_addend1);
		code.push_str(", ");
		code.push_str(register_addend2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn mullo(&mut self, register_product: &str, register_multiplicand1: &str, register_multiplicand2: &str) -> String
	{
		let mut code = String::new();
		code.push_str("subu ");
		code.push_str(register_product);
		code.push_str(", ");
		code.push_str(register_multiplicand1);
		code.push_str(", ");
		code.push_str(register_multiplicand2);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn sw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("sw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn lw(&mut self, register_target: &str, offset: u16, register_address: &str) -> String
	{
		let mut code = String::new();
		code.push_str("lw ");
		code.push_str(register_target);
		code.push_str(", ");
		code.push_str(&*offset.to_string());
		code.push_str(" (");
		code.push_str(register_address);
		code.push_str(")\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn push(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("push ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn pop(&mut self, register_target: &str) -> String
	{
		let mut code = String::new();
		code.push_str("pop ");
		code.push_str(register_target);
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn call(&mut self, function_label: &str) -> String
	{
		let mut code = String::new();
		code.push_str("call ");
		code.push_str(function_label);
		code.push_str("\n");
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}

	pub fn nop(&mut self) -> String
	{
		let mut code = String::new();
		code.push_str("nop");
		code.push_str("\n");

		self.code.push_str(&*code);
		return code;
	}
}
<|endoftext|>


<commit_before>// 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.

use r2::point::Point;
use s2::point::Point as s2Point;
use std::cmp::Ordering;

// Edge represents a geodesic edge consisting of two vertices. Zero-length edges are
// allowed, and can be used to represent points.

pub struct Edge {
    v0: Point,
    v1: Point,
}

impl Eq for Edge {}

impl Ord for Edge {
    fn cmp(&self, other: &Edge) -> Ordering {
        let v0cmp = self.v0.cmp(&other.v0);
        if v0cmp != Ordering::Equal {
            v0cmp
        } else {
            self.v0.cmp(&other.v1)
        }
    }
}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Edge) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Edge) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}

// sortEdges sorts the slice of Edges in place.
pub fn sort_edges(mut e: Vec<Edge>) {
    e.sort()
}

// edges implements the Sort interface for slices of Edge.
type Edges = Vec<Edge>;

trait EdgesMethods {
    fn less(&self, i: i64, j: i64) -> bool;
}

impl EdgesMethods for Edges {
    fn less(&self, i: i64, j: i64) -> bool {
        self[i as usize].cmp(&self[j as usize]) == Ordering::Less
    }
}

// Shapeedge_id is a unique identifier for an Edge within an ShapeIndex,
// consisting of a (shape_id, edge_id) pair.
pub struct ShapeEdgeID {
    shape_id: i32,
    edge_id: i32,
}

impl ShapeEdgeID {
    // Cmp compares the two Shapeedge_ids and returns
    //
    //   -1 if s <  other
    //    0 if s == other
    //   +1 if s >  other
    //
    // The two are compared first by shape id and then by edge id.
    pub fn cmp(&self, other: ShapeEdgeID) -> i64 {
        if self.shape_id < other.shape_id {
            return -1;
        } else if self.shape_id > other.shape_id {
            return 1;
        }

        if self.edge_id < other.edge_id {
            return -1;
        } else if self.edge_id > other.edge_id {
            return 1;
        }
        return 0;
    }
}

// ShapeEdge represents a Shapeedge_id with the two endpoints of that Edge.
pub struct ShapeEdge {
    id: ShapeEdgeID,
    edge: Edge,
}

// Chain represents a range of edge IDs corresponding to a chain of connected
// edges, specified as a (start, length) pair. The chain is defined to consist of
// edge IDs {start, start + 1, ..., start + length - 1}.
pub struct Chain {
    start: i64,
    length: i64,
}

// ChainPosition represents the position of an edge within a given edge chain,
// specified as a (chainID, offset) pair. Chains are numbered sequentially
// starting from zero, and offsets are measured from the start of each chain.
pub struct ChainPosition {
    chain_id: i64,
    offset: i64,
}

// A ReferencePoint consists of a point and a boolean indicating whether the point
// is contained by a particular shape.
pub struct ReferencePoint {
    point: s2Point,
    contained: bool,
}

// OriginReferencePoint returns a ReferencePoint with the given value for
// contained and the origin point. It should be used when all points or no
// points are contained.
pub fn origin_reference_point(contained: bool) -> ReferencePoint {
    ReferencePoint {
        point: s2Point::origin(),
        contained: contained,
    }
}

// Shape represents polygonal geometry in a flexible way. It is organized as a
// collection of edges that optionally defines an interior. All geometry
// represented by a given Shape must have the same dimension, which means that
// an Shape can represent either a set of points, a set of polylines, or a set
// of polygons.
//
// Shape is defined as an interface in order to give clients control over the
// underlying data representation. Sometimes an Shape does not have any data of
// its own, but instead wraps some other type.
//
// Shape operations are typically defined on a ShapeIndex rather than
// individual shapes. An ShapeIndex is simply a collection of Shapes,
// possibly of different dimensions (e.g. 10 points and 3 polygons), organized
// into a data structure for efficient edge access.
//
// The edges of a Shape are indexed by a contiguous range of edge IDs
// starting at 0. The edges are further subdivided into chains, where each
// chain consists of a sequence of edges connected end-to-end (a polyline).
// For example, a Shape representing two polylines AB and CDE would have
// three edges (AB, CD, DE) grouped into two chains: (AB) and (CD, DE).
// Similarly, an Shape representing 5 points would have 5 chains consisting
// of one edge each.
//
// Shape has methods that allow edges to be accessed either using the global
// numbering (edge ID) or within a particular chain. The global numbering is
// sufficient for most purposes, but the chain representation is useful for
// certain algorithms such as intersection (see BooleanOperation).
pub trait Shape {
    // NumEdges returns the number of edges in this shape.
    fn num_edges(&self) -> i64;

    // Edge returns the edge for the given edge index.
    fn edge(&self, i: i64) -> Edge;

    // ReferencePoint returns an arbitrary reference point for the shape. (The
    // containment boolean value must be false for shapes that do not have an interior.)
    //
    // This reference point may then be used to compute the containment of other
    // points by counting edge crossings.
    fn reference_point(&self) -> ReferencePoint;

    // NumChains reports the number of contiguous edge chains in the shape.
    // For example, a shape whose edges are [AB, BC, CD, AE, EF] would consist
    // of two chains (AB,BC,CD and AE,EF). Every chain is assigned a chain Id
    // numbered sequentially starting from zero.
    //
    // Note that it is always acceptable to implement this method by returning
    // NumEdges, i.e. every chain consists of a single edge, but this may
    // reduce the efficiency of some algorithms.
    fn num_chains(&self) -> i64;

    // Chain returns the range of edge IDs corresponding to the given edge chain.
    // Edge chains must form contiguous, non-overlapping ranges that cover
    // the entire range of edge IDs. This is spelled out more formally below:
    //
    //  0 <= i < NumChains()
    //  Chain(i).length > 0, for all i
    //  Chain(0).start == 0
    //  Chain(i).start + Chain(i).length == Chain(i+1).start, for i < NumChains()-1
    //  Chain(i).start + Chain(i).length == NumEdges(), for i == NumChains()-1
    fn chain(&self, chain_id: i64) -> Chain;

    // ChainEdgeReturns the edge at offset "offset" within edge chain "chainID".
    // Equivalent to "shape.Edge(shape.Chain(chainID).start + offset)"
    // but more efficient.
    fn chain_edge(&self, chain_id: i64, offset: i64) -> Edge;

    // ChainPosition finds the chain containing the given edge, and returns the
    // position of that edge as a ChainPosition(chainID, offset) pair.
    //
    //  shape.Chain(pos.chainID).start + pos.offset == edge_id
    //  shape.Chain(pos.chainID+1).start > edge_id
    //
    // where pos == shape.ChainPosition(edge_id).
    fn chain_position(&self, edge_id: i64) -> ChainPosition;

    // Dimension returns the dimension of the geometry represented by this shape,
    // either 0, 1 or 2 for point, polyline and polygon geometry respectively.
    //
    //  0 - Point geometry. Each point is represented as a degenerate edge.
    //
    //  1 - Polyline geometry. Polyline edges may be degenerate. A shape may
    //      represent any number of polylines. Polylines edges may intersect.
    //
    //  2 - Polygon geometry. Edges should be oriented such that the polygon
    //      interior is always on the left. In theory the edges may be returned
    //      in any order, but typically the edges are organized as a collection
    //      of edge chains where each chain represents one polygon loop.
    //      Polygons may have degeneracies (e.g., degenerate edges or sibling
    //      pairs consisting of an edge and its corresponding reversed edge).
    //      A polygon loop may also be full (containing all points on the
    //      sphere); by convention this is represented as a chain with no edges.
    //      (See laxPolygon for details.)
    //
    // This method allows degenerate geometry of different dimensions
    // to be distinguished, e.g. it allows a point to be distinguished from a
    // polyline or polygon that has been simplified to a single point.
    fn dimension(&self) -> i64;

    // IsEmpty reports whether the Shape contains no points. (Note that the full
    // polygon is represented as a chain with zero edges.)
    fn is_empty(&self) -> bool;

    // IsFull reports whether the Shape contains all points on the sphere.
    fn is_full(&self) -> bool;
}

// defaultShapeIsEmpty reports whether this shape contains no points.
pub fn default_shape_is_empty(s: Box<Shape>) -> bool {
    return s.num_edges() == 0 && (s.dimension() != 2 || s.num_chains() == 0);
}

// defaultShapeIsFull reports whether this shape contains all points on the sphere.
pub fn default_shape_is_full(s: Box<Shape>) -> bool {
    return s.num_edges() == 0 && s.dimension() == 2 && s.num_chains() > 0;
}
<commit_msg>fix all warnings<commit_after>// 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.

use r2::point::Point;
use s2::point::Point as s2Point;
use std::cmp::Ordering;

// Edge represents a geodesic edge consisting of two vertices. Zero-length edges are
// allowed, and can be used to represent points.

pub struct Edge {
    v0: Point,
    v1: Point,
}

impl Eq for Edge {}

impl Ord for Edge {
    fn cmp(&self, other: &Edge) -> Ordering {
        let v0cmp = self.v0.cmp(&other.v0);
        if v0cmp != Ordering::Equal {
            v0cmp
        } else {
            self.v0.cmp(&other.v1)
        }
    }
}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Edge) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Edge) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}

// sortEdges sorts the slice of Edges in place.
pub fn sort_edges(mut e: Vec<Edge>) {
    e.sort()
}

// edges implements the Sort interface for slices of Edge.
#[allow(unused)]
type Edges = Vec<Edge>;

trait EdgesMethods {
    fn less(&self, i: i64, j: i64) -> bool;
}

impl EdgesMethods for Edges {
    fn less(&self, i: i64, j: i64) -> bool {
        self[i as usize].cmp(&self[j as usize]) == Ordering::Less
    }
}

// Shapeedge_id is a unique identifier for an Edge within an ShapeIndex,
// consisting of a (shape_id, edge_id) pair.
pub struct ShapeEdgeID {
    shape_id: i32,
    edge_id: i32,
}

impl ShapeEdgeID {
    // Cmp compares the two Shapeedge_ids and returns
    //
    //   -1 if s <  other
    //    0 if s == other
    //   +1 if s >  other
    //
    // The two are compared first by shape id and then by edge id.
    pub fn cmp(&self, other: ShapeEdgeID) -> i64 {
        if self.shape_id < other.shape_id {
            return -1;
        } else if self.shape_id > other.shape_id {
            return 1;
        }

        if self.edge_id < other.edge_id {
            return -1;
        } else if self.edge_id > other.edge_id {
            return 1;
        }
        return 0;
    }
}

// ShapeEdge represents a Shapeedge_id with the two endpoints of that Edge.
pub struct ShapeEdge {
    #[allow(unused)]
    id: ShapeEdgeID,
    #[allow(unused)]
    edge: Edge,
}

// Chain represents a range of edge IDs corresponding to a chain of connected
// edges, specified as a (start, length) pair. The chain is defined to consist of
// edge IDs {start, start + 1, ..., start + length - 1}.
pub struct Chain {
    #[allow(unused)]
    start: i64,
    #[allow(unused)]
    length: i64,
}

// ChainPosition represents the position of an edge within a given edge chain,
// specified as a (chainID, offset) pair. Chains are numbered sequentially
// starting from zero, and offsets are measured from the start of each chain.
pub struct ChainPosition {
    #[allow(unused)]
    chain_id: i64,
    #[allow(unused)]
    offset: i64,
}

// A ReferencePoint consists of a point and a boolean indicating whether the point
// is contained by a particular shape.
pub struct ReferencePoint {
    #[allow(unused)]
    point: s2Point,
    #[allow(unused)]
    contained: bool,
}

// OriginReferencePoint returns a ReferencePoint with the given value for
// contained and the origin point. It should be used when all points or no
// points are contained.
pub fn origin_reference_point(contained: bool) -> ReferencePoint {
    ReferencePoint {
        point: s2Point::origin(),
        contained: contained,
    }
}

// Shape represents polygonal geometry in a flexible way. It is organized as a
// collection of edges that optionally defines an interior. All geometry
// represented by a given Shape must have the same dimension, which means that
// an Shape can represent either a set of points, a set of polylines, or a set
// of polygons.
//
// Shape is defined as an interface in order to give clients control over the
// underlying data representation. Sometimes an Shape does not have any data of
// its own, but instead wraps some other type.
//
// Shape operations are typically defined on a ShapeIndex rather than
// individual shapes. An ShapeIndex is simply a collection of Shapes,
// possibly of different dimensions (e.g. 10 points and 3 polygons), organized
// into a data structure for efficient edge access.
//
// The edges of a Shape are indexed by a contiguous range of edge IDs
// starting at 0. The edges are further subdivided into chains, where each
// chain consists of a sequence of edges connected end-to-end (a polyline).
// For example, a Shape representing two polylines AB and CDE would have
// three edges (AB, CD, DE) grouped into two chains: (AB) and (CD, DE).
// Similarly, an Shape representing 5 points would have 5 chains consisting
// of one edge each.
//
// Shape has methods that allow edges to be accessed either using the global
// numbering (edge ID) or within a particular chain. The global numbering is
// sufficient for most purposes, but the chain representation is useful for
// certain algorithms such as intersection (see BooleanOperation).
pub trait Shape {
    // NumEdges returns the number of edges in this shape.
    fn num_edges(&self) -> i64;

    // Edge returns the edge for the given edge index.
    fn edge(&self, i: i64) -> Edge;

    // ReferencePoint returns an arbitrary reference point for the shape. (The
    // containment boolean value must be false for shapes that do not have an interior.)
    //
    // This reference point may then be used to compute the containment of other
    // points by counting edge crossings.
    fn reference_point(&self) -> ReferencePoint;

    // NumChains reports the number of contiguous edge chains in the shape.
    // For example, a shape whose edges are [AB, BC, CD, AE, EF] would consist
    // of two chains (AB,BC,CD and AE,EF). Every chain is assigned a chain Id
    // numbered sequentially starting from zero.
    //
    // Note that it is always acceptable to implement this method by returning
    // NumEdges, i.e. every chain consists of a single edge, but this may
    // reduce the efficiency of some algorithms.
    fn num_chains(&self) -> i64;

    // Chain returns the range of edge IDs corresponding to the given edge chain.
    // Edge chains must form contiguous, non-overlapping ranges that cover
    // the entire range of edge IDs. This is spelled out more formally below:
    //
    //  0 <= i < NumChains()
    //  Chain(i).length > 0, for all i
    //  Chain(0).start == 0
    //  Chain(i).start + Chain(i).length == Chain(i+1).start, for i < NumChains()-1
    //  Chain(i).start + Chain(i).length == NumEdges(), for i == NumChains()-1
    fn chain(&self, chain_id: i64) -> Chain;

    // ChainEdgeReturns the edge at offset "offset" within edge chain "chainID".
    // Equivalent to "shape.Edge(shape.Chain(chainID).start + offset)"
    // but more efficient.
    fn chain_edge(&self, chain_id: i64, offset: i64) -> Edge;

    // ChainPosition finds the chain containing the given edge, and returns the
    // position of that edge as a ChainPosition(chainID, offset) pair.
    //
    //  shape.Chain(pos.chainID).start + pos.offset == edge_id
    //  shape.Chain(pos.chainID+1).start > edge_id
    //
    // where pos == shape.ChainPosition(edge_id).
    fn chain_position(&self, edge_id: i64) -> ChainPosition;

    // Dimension returns the dimension of the geometry represented by this shape,
    // either 0, 1 or 2 for point, polyline and polygon geometry respectively.
    //
    //  0 - Point geometry. Each point is represented as a degenerate edge.
    //
    //  1 - Polyline geometry. Polyline edges may be degenerate. A shape may
    //      represent any number of polylines. Polylines edges may intersect.
    //
    //  2 - Polygon geometry. Edges should be oriented such that the polygon
    //      interior is always on the left. In theory the edges may be returned
    //      in any order, but typically the edges are organized as a collection
    //      of edge chains where each chain represents one polygon loop.
    //      Polygons may have degeneracies (e.g., degenerate edges or sibling
    //      pairs consisting of an edge and its corresponding reversed edge).
    //      A polygon loop may also be full (containing all points on the
    //      sphere); by convention this is represented as a chain with no edges.
    //      (See laxPolygon for details.)
    //
    // This method allows degenerate geometry of different dimensions
    // to be distinguished, e.g. it allows a point to be distinguished from a
    // polyline or polygon that has been simplified to a single point.
    fn dimension(&self) -> i64;

    // IsEmpty reports whether the Shape contains no points. (Note that the full
    // polygon is represented as a chain with zero edges.)
    fn is_empty(&self) -> bool;

    // IsFull reports whether the Shape contains all points on the sphere.
    fn is_full(&self) -> bool;
}

// defaultShapeIsEmpty reports whether this shape contains no points.
pub fn default_shape_is_empty(s: Box<dyn Shape>) -> bool {
    return s.num_edges() == 0 && (s.dimension() != 2 || s.num_chains() == 0);
}

// defaultShapeIsFull reports whether this shape contains all points on the sphere.
pub fn default_shape_is_full(s: Box<dyn Shape>) -> bool {
    return s.num_edges() == 0 && s.dimension() == 2 && s.num_chains() > 0;
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A simple application that uses glutin to open a window for Servo to display in.

#![feature(box_syntax)]
#![feature(struct_field_attributes)]

#[macro_use] extern crate bitflags;
extern crate compositing;
#[cfg(target_os = "android")] extern crate egl;
extern crate euclid;
extern crate gleam;
extern crate glutin;
#[macro_use] extern crate log;
extern crate msg;
extern crate net_traits;
#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys;
extern crate script_traits;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_url;
extern crate style_traits;
extern crate webrender_traits;

#[cfg(target_os = "windows")] extern crate winapi;
#[cfg(target_os = "windows")] extern crate user32;
#[cfg(target_os = "windows")] extern crate gdi32;

use compositing::windowing::WindowEvent;
use servo_config::opts;
use std::rc::Rc;
use window::Window;

pub mod window;

pub type WindowID = glutin::WindowID;

pub trait NestedEventLoopListener {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool;
}

pub fn create_window(parent: Option<WindowID>) -> Rc<Window> {
    // Read command-line options.
    let opts = opts::get();
    let foreground = opts.output_file.is_none() && !opts.headless;

    // Open a window.
    Window::new(foreground, opts.initial_window_size, parent)
}
<commit_msg>Fix warn stable_features<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A simple application that uses glutin to open a window for Servo to display in.

#![feature(box_syntax)]

#[macro_use] extern crate bitflags;
extern crate compositing;
#[cfg(target_os = "android")] extern crate egl;
extern crate euclid;
extern crate gleam;
extern crate glutin;
#[macro_use] extern crate log;
extern crate msg;
extern crate net_traits;
#[cfg(any(target_os = "linux", target_os = "macos"))] extern crate osmesa_sys;
extern crate script_traits;
extern crate servo_config;
extern crate servo_geometry;
extern crate servo_url;
extern crate style_traits;
extern crate webrender_traits;

#[cfg(target_os = "windows")] extern crate winapi;
#[cfg(target_os = "windows")] extern crate user32;
#[cfg(target_os = "windows")] extern crate gdi32;

use compositing::windowing::WindowEvent;
use servo_config::opts;
use std::rc::Rc;
use window::Window;

pub mod window;

pub type WindowID = glutin::WindowID;

pub trait NestedEventLoopListener {
    fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool;
}

pub fn create_window(parent: Option<WindowID>) -> Rc<Window> {
    // Read command-line options.
    let opts = opts::get();
    let foreground = opts.output_file.is_none() && !opts.headless;

    // Open a window.
    Window::new(foreground, opts.initial_window_size, parent)
}
<|endoftext|>


<commit_before>use parser;

use super::expand_macros;

#[test]
fn test_comma() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Comma<E>: Vec<E> =
       ~v:(~E \",\")* ~e:E? =>
           v.into_iter().chain(e.into_iter()).collect();

    Ids = Comma<\"Id\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Ids = `Comma<\"Id\">`;

    `Comma<\"Id\">`: Vec<`\"Id\"`> =
        ~v:(~\"Id\" \",\")* ~e:\"Id\"? =>
           v.into_iter().chain(e.into_iter()).collect();
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    assert_eq!(actual, expected);
}
<commit_msg>Add a test for condition matching<commit_after>use parser;

use super::expand_macros;

#[test]
fn test_comma() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Comma<E>: Vec<E> =
       ~v:(~E \",\")* ~e:E? =>
           v.into_iter().chain(e.into_iter()).collect();

    Ids = Comma<\"Id\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Ids = `Comma<\"Id\">`;

    `Comma<\"Id\">`: Vec<`\"Id\"`> =
        ~v:(~\"Id\" \",\")* ~e:\"Id\"? =>
           v.into_iter().chain(e.into_iter()).collect();
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    assert_eq!(actual, expected);
}

#[test]
fn test_if_match() {
    let grammar = parser::parse_grammar("
grammar Foo {
    Expr<E> = {
       A if E == \"A*C\";
       B if E ~~ \"^A*C$\";
       C if E != \"A*C\";
       D if E !~ \"^A*C$\";
    };

    Expr1 = Expr<\"A*C\">;
    Expr2 = Expr<\"AAC\">;
    Expr3 = Expr<\"ABC\">;
}
").unwrap();

    let actual = expand_macros(grammar).unwrap();

    let expected = parser::parse_grammar("
grammar Foo {
    Expr1 = `Expr<\"A*C\">`;
    Expr2 = `Expr<\"AAC\">`;
    Expr3 = `Expr<\"ABC\">`;

    `Expr<\"ABC\">` = { C; D; };
    `Expr<\"AAC\">` = { B; C; };
    `Expr<\"A*C\">` = { A; D; };
}
").unwrap();

    println!("Actual:");
    println!("{:#?}", actual);
    println!("Expected:");
    println!("{:#?}", expected);

    assert_eq!(actual, expected);
}
<|endoftext|>


<commit_before>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_test(mut test: Json) -> TestCase {
    unimplemented!()
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .map(parse_test)
}
<commit_msg>wycats said to iterate and call map on the iterator (wouldn't've guessed that)<commit_after>#![cfg(test)]

use std::collections::HashMap;
use rustc_serialize::json;
use rustc_serialize::json::{decode, Json, Object};
use rustc_serialize::{Decoder, Decodable};
use std::io::prelude::*;
use std::fs::File;
use token::{Token, ReservedWord};

pub struct ExpectPass {
    source: String,
    expected: Json,
    options: Option<Json>
}

pub struct ExpectFail {
    source: String,
    error: String,
    options: Option<Json>
}

pub enum TestCase {
    Pass(ExpectPass),
    Fail(ExpectFail)
}

trait JsonExt {
    fn into_array(self) -> json::Array;
    fn into_string(self) -> String;
    fn into_string_opt(self) -> Option<String>;
}

impl JsonExt for Json {
    fn into_array(self) -> json::Array {
        match self {
            Json::Array(array) => array,
            _ => panic!("expected array")
        }
    }
    fn into_string(self) -> String {
        match self {
            Json::String(string) => string,
            _ => panic!("expected string")
        }
    }
    fn into_string_opt(self) -> Option<String> {
        match self {
            Json::Null => None,
            Json::String(string) => Some(string),
            _ => panic!("expected string or null")
        }
    }
}

fn parse_test(mut test: Json) -> TestCase {
    unimplemented!()
}

pub fn read_tests(path: &str) -> Vec<TestCase> {
    let mut f: File = File::open(path).unwrap();
    let mut s = String::new();
    f.read_to_string(&mut s);
    parse_tests(&s)
}

pub fn parse_tests(src: &str) -> Vec<TestCase> {
    let data: Json = src.parse().unwrap();
    data.into_array()
        .into_iter()
        .map(parse_test)
        .collect()
}
<|endoftext|>


<commit_before>generate_error_module!(
    generate_error_types!(MailError, MailErrorKind,
        RefCreationError => "Error creating a reference to a file/directory",
        MailParsingError => "Error while parsing mail",

        FetchByHashError => "Error fetching mail from Store by hash",
        FetchError       => "Error fetching mail from Store",
        IOError => "IO Error"
    );
);

pub use self::error::MailError;
pub use self::error::MailErrorKind;
pub use self::error::MapErrInto;

<commit_msg>Add error kind for ref handling errors<commit_after>generate_error_module!(
    generate_error_types!(MailError, MailErrorKind,
        RefCreationError => "Error creating a reference to a file/directory",
        RefHandlingError => "Error while handling the internal reference object",
        MailParsingError => "Error while parsing mail",

        FetchByHashError => "Error fetching mail from Store by hash",
        FetchError       => "Error fetching mail from Store",
        IOError => "IO Error"
    );
);

pub use self::error::MailError;
pub use self::error::MailErrorKind;
pub use self::error::MapErrInto;

<|endoftext|>


<commit_before>#![feature(type_ascription)]

extern crate env_logger;
extern crate clap;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate rand;
#[macro_use]
extern crate log;
extern crate colored;

extern crate iron;
extern crate params;
extern crate hyper;
extern crate router;

extern crate exonum;
extern crate blockchain_explorer;
extern crate timestamping;

use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::path::Path;
use std::thread;

use iron::prelude::*;
use iron::status;
use iron::mime::{Mime, TopLevel, SubLevel};
use iron::headers;
use hyper::header::{ContentDisposition, DispositionType, DispositionParam, Charset};
use params::{Params, Value};
use router::Router;

use serde_json::value::ToJson;
use clap::{Arg, App, SubCommand};
use log::{LogRecord, LogLevel};
use env_logger::LogBuilder;
use colored::*;

use exonum::node::{Node, Configuration, TxSender, NodeChannel};
use exonum::storage::{Database, MemoryDB, LevelDB, LevelDBOptions, Map};
use exonum::storage::Error as StorageError;
use exonum::crypto::{gen_keypair, HexValue, FromHexError, hash, Hash};
use exonum::config::ConfigFile;
use exonum::node::config::GenesisConfig;
use exonum::events::Error as EventsError;
use exonum::blockchain::Blockchain;

use timestamping::{TimestampingBlockchain, TimestampTx, Content, TIMESTAMPING_FILE_SIZE_LIMIT};

pub type TimestampTxSender<B> = TxSender<B, NodeChannel<B>>;

#[derive(Clone)]
pub struct TimestampingApi<D: Database> {
    blockchain: TimestampingBlockchain<D>,
    channel: TimestampTxSender<TimestampingBlockchain<D>>,
}

#[derive(Debug)]
enum ApiError {
    Storage(StorageError),
    Events(EventsError),
    FromHex(FromHexError),
    Io(std::io::Error),
    FileNotFound,
    FileToBig,
    FileExists,
}

impl std::fmt::Display for ApiError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl std::error::Error for ApiError {
    fn description(&self) -> &str {
        "Api error"
    }
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<StorageError> for ApiError {
    fn from(e: StorageError) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<EventsError> for ApiError {
    fn from(e: EventsError) -> ApiError {
        ApiError::Events(e)
    }
}

impl From<FromHexError> for ApiError {
    fn from(e: FromHexError) -> ApiError {
        ApiError::FromHex(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        let code = status::BadRequest;
        let string = e.to_string();

        IronError {
            error: Box::new(e),
            response: Response::with((code, string)),
        }
    }
}

impl<D> TimestampingApi<D>
    where D: Database
{
    fn put_file(&self, file: &params::File, description: &str) -> Result<TimestampTx, ApiError> {
        if file.size > TIMESTAMPING_FILE_SIZE_LIMIT {
            return Err(ApiError::FileToBig);
        }

        let file_name = file.filename.clone().unwrap_or("None".into());
        let mime = file.content_type.to_string();
        let mut file = File::open(&file.path)?;

        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        let hash = hash(buf.as_ref());
        // TODO add checks for already stored files
        if self.blockchain.view().contents().get(&hash)?.is_some() {
            return Err(ApiError::FileExists);
        }

        // Create transaction
        let (_, dummy_key) = gen_keypair();
        let ts = time::now().to_timespec();
        // FIXME avoid reallocations
        let tx = TimestampTx::new(&file_name, &description, &mime, ts, &hash, buf.as_ref(), &dummy_key);
        self.channel.send(tx.clone())?;

        Ok(tx)
    }

    fn get_file(&self, hash_str: &str) -> Result<Content, ApiError> {
        let hash = Hash::from_hex(hash_str)?;
        let view = self.blockchain.view();
        view.contents()
            .get(&hash)?
            .ok_or_else(|| ApiError::FileNotFound)
    }
}

fn run_node<D: Database>(blockchain: TimestampingBlockchain<D>,
                         node_cfg: Configuration,
                         port: Option<u16>) {
    if let Some(port) = port {
        let mut node = Node::new(blockchain.clone(), node_cfg.clone());
        let channel = node.channel();

        let api_thread = thread::spawn(move || {
            let timestamping_api = TimestampingApi {
                channel: channel.clone(),
                blockchain: blockchain.clone(),
            };

            let mut router = Router::new();

            let api = timestamping_api.clone();
            let get_file = move |req: &mut Request| -> IronResult<Response> {
                let ref hash = req.extensions.get::<Router>().unwrap().find("hash").unwrap();
                let content = api.get_file(&hash)?;

                let mime: Mime = content.mime().parse().unwrap();
                let data = content.data().to_vec();
                let len = data.len() as u64;

                let mut response = Response::with((status::Ok, data));
                response.set_mut(mime);
                response.headers.set(headers::ContentLength(len));
                response.headers.set(ContentDisposition {
                    disposition: DispositionType::Attachment,
                    parameters: vec![DispositionParam::Filename(
                    Charset::Iso_8859_1, // The character set for the bytes of the filename
                    None, // The optional language tag (see `language-tag` crate)
                    content.file_name().as_bytes().to_vec() // the actual bytes of the filename
                    )]
                });
                Ok(response)
            };

            // Receive a message by POST and play it back.
            let api = timestamping_api.clone();
            let put_file = move |req: &mut Request| -> IronResult<Response> {
                let map = req.get_ref::<Params>().unwrap();

                let description = if let Some(&Value::String(ref txt)) = map.find(&["description"]) {
                    txt
                } else {
                    ""
                };

                if let Some(&Value::File(ref file)) = map.find(&["content"]) {
                    let tx = api.put_file(file, description)?;
                    let content_type = Mime(TopLevel::Application, SubLevel::Json, Vec::new());
                    let response = Response::with((content_type, status::Ok, tx.to_json().to_string()));
                    return Ok(response);
                } else {
                    Err(ApiError::FileNotFound.into())
                }
            };

            let api = timestamping_api.clone();
            let file_info = move |req: &mut Request| -> IronResult<Response> {
                let ref hash = req.extensions.get::<Router>().unwrap().find("hash").unwrap();
                let content = api.get_file(&hash)?;

                let content_type = Mime(TopLevel::Application, SubLevel::Json, Vec::new());
                let response = Response::with((content_type, status::Ok, content.to_json().to_string()));
                Ok(response)
            };

            router.get("/timestamping/content/:hash", get_file, "get");
            router.get("/timestamping/info/:hash", file_info, "info");
            router.post("/timestamping/content", put_file, "push");

            let host = format!("localhost:{}", port);
            Iron::new(router).http(host.as_str()).unwrap();
        });

        node.run().unwrap();
        api_thread.join().unwrap();
    } else {
        Node::new(blockchain, node_cfg).run().unwrap();
    }
}

fn main() {
    let format = |record: &LogRecord| {
        let now = time::now_utc();
        let level = match record.level() {
            LogLevel::Error => "ERROR".red(),
            LogLevel::Warn => "WARN".yellow(),
            LogLevel::Info => "INFO".green(),
            LogLevel::Debug => "DEBUG".cyan(),
            LogLevel::Trace => "TRACE".white(),
        };
        format!("{} - [ {} ] - {}",
                now.asctime().to_string().bold(),
                level,
                record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init().unwrap();

    let app = App::new("Simple timestamping demo program")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Aleksey S. <aleksei.sidorov@xdev.re>")
        .about("Demo timestamping validator node")
        .arg(Arg::with_name("CONFIG")
            .short("c")
            .long("config")
            .value_name("CONFIG_PATH")
            .help("Sets a node config file")
            .required(true)
            .takes_value(true))
        .subcommand(SubCommand::with_name("generate")
            .about("Generates default configuration file")
            .version(env!("CARGO_PKG_VERSION"))
            .author("Aleksey S. <aleksei.sidorov@xdev.re>")
            .arg(Arg::with_name("START_PORT")
                .short("p")
                .long("port")
                .value_name("START_PORT")
                .help("Port for first validator")
                .takes_value(true))
            .arg(Arg::with_name("COUNT")
                .help("Validators count")
                .required(true)
                .index(1)))
        .subcommand(SubCommand::with_name("run")
            .about("Run demo node with the given validator id")
            .version(env!("CARGO_PKG_VERSION"))
            .author("Aleksey S. <aleksei.sidorov@xdev.re>")
            .arg(Arg::with_name("LEVELDB_PATH")
                .short("d")
                .long("leveldb-path")
                .value_name("LEVELDB_PATH")
                .help("Use leveldb database with the given path")
                .takes_value(true))
            .arg(Arg::with_name("HTTP_PORT")
                .short("p")
                .long("port")
                .value_name("HTTP_PORT")
                .help("Run http server on given port")
                .takes_value(true))
            .arg(Arg::with_name("PEERS")
                .long("known-peers")
                .value_name("PEERS")
                .help("Comma separated list of known validator ids")
                .takes_value(true))
            .arg(Arg::with_name("VALIDATOR")
                .help("Sets a validator id")
                .required(true)
                .index(1)));

    let matches = app.get_matches();
    let path = Path::new(matches.value_of("CONFIG").unwrap());
    match matches.subcommand() {
        ("generate", Some(matches)) => {
            let count: u8 = matches.value_of("COUNT").unwrap().parse().unwrap();
            let port: Option<u16> = matches.value_of("START_PORT").map(|x| x.parse().unwrap());
            let cfg = GenesisConfig::gen(count, port);
            ConfigFile::save(&cfg, &path).unwrap();
            println!("The configuration was successfully written to file {:?}",
                     path);
        }
        ("run", Some(matches)) => {
            let cfg: GenesisConfig = ConfigFile::load(path).unwrap();
            let idx: usize = matches.value_of("VALIDATOR").unwrap().parse().unwrap();
            let port: Option<u16> = matches.value_of("HTTP_PORT").map(|x| x.parse().unwrap());
            let peers = match matches.value_of("PEERS") {
                Some(string) => {
                    string.split(" ")
                        .map(|x| -> usize { x.parse().unwrap() })
                        .map(|x| cfg.validators[x].address)
                        .collect()
                }
                None => {
                    cfg.validators
                        .iter()
                        .map(|v| v.address)
                        .collect()
                }
            };
            let node_cfg = cfg.gen_node_configuration(idx, peers);
            match matches.value_of("LEVELDB_PATH") {
                Some(ref db_path) => {
                    println!("Using levedb storage with path: {}", db_path);
                    let mut options = LevelDBOptions::new();
                    options.create_if_missing = true;
                    let leveldb = LevelDB::new(&Path::new(db_path), options).unwrap();

                    let blockchain = TimestampingBlockchain { db: leveldb };
                    run_node(blockchain, node_cfg, port);
                }
                None => {
                    println!("Using memorydb storage");

                    let blockchain = TimestampingBlockchain { db: MemoryDB::new() };
                    run_node(blockchain, node_cfg, port);
                }
            };
        }
        _ => {
            unreachable!("Wrong subcommand");
        }
    }
}
<commit_msg>Improve error messages<commit_after>#![feature(type_ascription)]

extern crate env_logger;
extern crate clap;
extern crate serde;
extern crate serde_json;
extern crate time;
extern crate rand;
#[macro_use]
extern crate log;
extern crate colored;

extern crate iron;
extern crate params;
extern crate hyper;
extern crate router;

extern crate exonum;
extern crate blockchain_explorer;
extern crate timestamping;

use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::path::Path;
use std::thread;
use std::collections::BTreeMap;

use iron::prelude::*;
use iron::status;
use iron::mime::{Mime, TopLevel, SubLevel};
use iron::headers;
use hyper::header::{ContentDisposition, DispositionType, DispositionParam, Charset};
use params::{Params, Value};
use router::Router;

use serde_json::value::ToJson;
use clap::{Arg, App, SubCommand};
use log::{LogRecord, LogLevel};
use env_logger::LogBuilder;
use colored::*;

use exonum::node::{Node, Configuration, TxSender, NodeChannel};
use exonum::storage::{Database, MemoryDB, LevelDB, LevelDBOptions, Map};
use exonum::storage::Error as StorageError;
use exonum::crypto::{gen_keypair, HexValue, FromHexError, hash, Hash};
use exonum::config::ConfigFile;
use exonum::node::config::GenesisConfig;
use exonum::events::Error as EventsError;
use exonum::blockchain::Blockchain;

use timestamping::{TimestampingBlockchain, TimestampTx, Content, TIMESTAMPING_FILE_SIZE_LIMIT};

pub type TimestampTxSender<B> = TxSender<B, NodeChannel<B>>;

#[derive(Clone)]
pub struct TimestampingApi<D: Database> {
    blockchain: TimestampingBlockchain<D>,
    channel: TimestampTxSender<TimestampingBlockchain<D>>,
}

#[derive(Debug)]
enum ApiError {
    Storage(StorageError),
    Events(EventsError),
    FromHex(FromHexError),
    Io(std::io::Error),
    FileNotFound(Hash),
    FileToBig,
    FileExists(Hash),
    IncorrectRequest,
}

impl std::fmt::Display for ApiError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl std::error::Error for ApiError {
    fn description(&self) -> &str {
        match *self {
            ApiError::Storage(_) => "Storage",
            ApiError::Events(_) => "Events",
            ApiError::FromHex(_) => "FromHex",
            ApiError::Io(_) => "Io",
            ApiError::FileNotFound(_) => "FileNotFound",
            ApiError::FileToBig => "FileToBig",
            ApiError::FileExists(_) => "FileExists",
            ApiError::IncorrectRequest => "IncorrectRequest",
        }
    }
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<StorageError> for ApiError {
    fn from(e: StorageError) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<EventsError> for ApiError {
    fn from(e: EventsError) -> ApiError {
        ApiError::Events(e)
    }
}

impl From<FromHexError> for ApiError {
    fn from(e: FromHexError) -> ApiError {
        ApiError::FromHex(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        use std::error::Error;

        let mut body = BTreeMap::new();
        body.insert("type", e.description().into());
        let code = match e {
            ApiError::FileExists(hash) => {
                body.insert("hash", hash.to_hex());
                status::Conflict
            }
            ApiError::FileNotFound(hash) => {
                body.insert("hash", hash.to_hex());
                status::Conflict
            }
            _ => {
                status::Conflict
            }
        };
        IronError {
            error: Box::new(e),
            response: Response::with((code, body.to_json().to_string())),
        }
    }
}

impl<D> TimestampingApi<D>
    where D: Database
{
    fn put_file(&self, file: &params::File, description: &str) -> Result<TimestampTx, ApiError> {
        if file.size > TIMESTAMPING_FILE_SIZE_LIMIT {
            return Err(ApiError::FileToBig);
        }

        let file_name = file.filename.clone().unwrap_or("None".into());
        let mime = file.content_type.to_string();
        let mut file = File::open(&file.path)?;

        let mut buf = Vec::new();
        file.read_to_end(&mut buf)?;
        let hash = hash(buf.as_ref());
        // TODO add checks for already stored files
        if self.blockchain.view().contents().get(&hash)?.is_some() {
            return Err(ApiError::FileExists(hash));
        }

        // Create transaction
        let (_, dummy_key) = gen_keypair();
        let ts = time::now().to_timespec();
        // FIXME avoid reallocations
        let tx = TimestampTx::new(&file_name, &description, &mime, ts, &hash, buf.as_ref(), &dummy_key);
        self.channel.send(tx.clone())?;

        Ok(tx)
    }

    fn get_file(&self, hash_str: &str) -> Result<Content, ApiError> {
        let hash = Hash::from_hex(hash_str)?;
        let view = self.blockchain.view();
        view.contents()
            .get(&hash)?
            .ok_or_else(|| ApiError::FileNotFound(hash))
    }
}

fn run_node<D: Database>(blockchain: TimestampingBlockchain<D>,
                         node_cfg: Configuration,
                         port: Option<u16>) {
    if let Some(port) = port {
        let mut node = Node::new(blockchain.clone(), node_cfg.clone());
        let channel = node.channel();

        let api_thread = thread::spawn(move || {
            let timestamping_api = TimestampingApi {
                channel: channel.clone(),
                blockchain: blockchain.clone(),
            };

            let mut router = Router::new();

            let api = timestamping_api.clone();
            let get_file = move |req: &mut Request| -> IronResult<Response> {
                let ref hash = req.extensions.get::<Router>().unwrap().find("hash").unwrap();
                let content = api.get_file(&hash)?;

                let mime: Mime = content.mime().parse().unwrap();
                let data = content.data().to_vec();
                let len = data.len() as u64;

                let mut response = Response::with((status::Ok, data));
                response.set_mut(mime);
                response.headers.set(headers::ContentLength(len));
                response.headers.set(ContentDisposition {
                    disposition: DispositionType::Attachment,
                    parameters: vec![DispositionParam::Filename(
                    Charset::Iso_8859_1, // The character set for the bytes of the filename
                    None, // The optional language tag (see `language-tag` crate)
                    content.file_name().as_bytes().to_vec() // the actual bytes of the filename
                    )]
                });
                Ok(response)
            };

            // Receive a message by POST and play it back.
            let api = timestamping_api.clone();
            let put_file = move |req: &mut Request| -> IronResult<Response> {
                let map = req.get_ref::<Params>().unwrap();

                let description = if let Some(&Value::String(ref txt)) = map.find(&["description"]) {
                    txt
                } else {
                    ""
                };

                if let Some(&Value::File(ref file)) = map.find(&["content"]) {
                    let tx = api.put_file(file, description)?;
                    let content_type = Mime(TopLevel::Application, SubLevel::Json, Vec::new());
                    let response = Response::with((content_type, status::Ok, tx.to_json().to_string()));
                    return Ok(response);
                } else {
                    Err(ApiError::IncorrectRequest.into())
                }
            };

            let api = timestamping_api.clone();
            let file_info = move |req: &mut Request| -> IronResult<Response> {
                let ref hash = req.extensions.get::<Router>().unwrap().find("hash").unwrap();
                let content = api.get_file(&hash)?;

                let content_type = Mime(TopLevel::Application, SubLevel::Json, Vec::new());
                let response = Response::with((content_type, status::Ok, content.to_json().to_string()));
                Ok(response)
            };

            router.get("/timestamping/content/:hash", get_file, "get");
            router.get("/timestamping/info/:hash", file_info, "info");
            router.post("/timestamping/content", put_file, "push");

            let host = format!("localhost:{}", port);
            Iron::new(router).http(host.as_str()).unwrap();
        });

        node.run().unwrap();
        api_thread.join().unwrap();
    } else {
        Node::new(blockchain, node_cfg).run().unwrap();
    }
}

fn main() {
    let format = |record: &LogRecord| {
        let now = time::now_utc();
        let level = match record.level() {
            LogLevel::Error => "ERROR".red(),
            LogLevel::Warn => "WARN".yellow(),
            LogLevel::Info => "INFO".green(),
            LogLevel::Debug => "DEBUG".cyan(),
            LogLevel::Trace => "TRACE".white(),
        };
        format!("{} - [ {} ] - {}",
                now.asctime().to_string().bold(),
                level,
                record.args())
    };

    let mut builder = LogBuilder::new();
    builder.format(format);

    if env::var("RUST_LOG").is_ok() {
        builder.parse(&env::var("RUST_LOG").unwrap());
    }

    builder.init().unwrap();

    let app = App::new("Simple timestamping demo program")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Aleksey S. <aleksei.sidorov@xdev.re>")
        .about("Demo timestamping validator node")
        .arg(Arg::with_name("CONFIG")
            .short("c")
            .long("config")
            .value_name("CONFIG_PATH")
            .help("Sets a node config file")
            .required(true)
            .takes_value(true))
        .subcommand(SubCommand::with_name("generate")
            .about("Generates default configuration file")
            .version(env!("CARGO_PKG_VERSION"))
            .author("Aleksey S. <aleksei.sidorov@xdev.re>")
            .arg(Arg::with_name("START_PORT")
                .short("p")
                .long("port")
                .value_name("START_PORT")
                .help("Port for first validator")
                .takes_value(true))
            .arg(Arg::with_name("COUNT")
                .help("Validators count")
                .required(true)
                .index(1)))
        .subcommand(SubCommand::with_name("run")
            .about("Run demo node with the given validator id")
            .version(env!("CARGO_PKG_VERSION"))
            .author("Aleksey S. <aleksei.sidorov@xdev.re>")
            .arg(Arg::with_name("LEVELDB_PATH")
                .short("d")
                .long("leveldb-path")
                .value_name("LEVELDB_PATH")
                .help("Use leveldb database with the given path")
                .takes_value(true))
            .arg(Arg::with_name("HTTP_PORT")
                .short("p")
                .long("port")
                .value_name("HTTP_PORT")
                .help("Run http server on given port")
                .takes_value(true))
            .arg(Arg::with_name("PEERS")
                .long("known-peers")
                .value_name("PEERS")
                .help("Comma separated list of known validator ids")
                .takes_value(true))
            .arg(Arg::with_name("VALIDATOR")
                .help("Sets a validator id")
                .required(true)
                .index(1)));

    let matches = app.get_matches();
    let path = Path::new(matches.value_of("CONFIG").unwrap());
    match matches.subcommand() {
        ("generate", Some(matches)) => {
            let count: u8 = matches.value_of("COUNT").unwrap().parse().unwrap();
            let port: Option<u16> = matches.value_of("START_PORT").map(|x| x.parse().unwrap());
            let cfg = GenesisConfig::gen(count, port);
            ConfigFile::save(&cfg, &path).unwrap();
            println!("The configuration was successfully written to file {:?}",
                     path);
        }
        ("run", Some(matches)) => {
            let cfg: GenesisConfig = ConfigFile::load(path).unwrap();
            let idx: usize = matches.value_of("VALIDATOR").unwrap().parse().unwrap();
            let port: Option<u16> = matches.value_of("HTTP_PORT").map(|x| x.parse().unwrap());
            let peers = match matches.value_of("PEERS") {
                Some(string) => {
                    string.split(" ")
                        .map(|x| -> usize { x.parse().unwrap() })
                        .map(|x| cfg.validators[x].address)
                        .collect()
                }
                None => {
                    cfg.validators
                        .iter()
                        .map(|v| v.address)
                        .collect()
                }
            };
            let node_cfg = cfg.gen_node_configuration(idx, peers);
            match matches.value_of("LEVELDB_PATH") {
                Some(ref db_path) => {
                    println!("Using levedb storage with path: {}", db_path);
                    let mut options = LevelDBOptions::new();
                    options.create_if_missing = true;
                    let leveldb = LevelDB::new(&Path::new(db_path), options).unwrap();

                    let blockchain = TimestampingBlockchain { db: leveldb };
                    run_node(blockchain, node_cfg, port);
                }
                None => {
                    println!("Using memorydb storage");

                    let blockchain = TimestampingBlockchain { db: MemoryDB::new() };
                    run_node(blockchain, node_cfg, port);
                }
            };
        }
        _ => {
            unreachable!("Wrong subcommand");
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use] pub mod error;

use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::{self, Read};

pub fn local_path(path: &str) -> io::Result<PathBuf> {
    let mut base = ::std::env::current_exe()?;
    base.pop();
    base.push(path);
    Ok(base)
}

/// Creates a file only if it doesn't already exist and returns whether it was created or not.
pub fn touch_file(path: &Path) -> io::Result<bool> {
    let exists = path.exists();

    if !exists {
        File::create(path)?;
    }

    Ok(exists)
}

pub fn verify_local_file(path: &str) -> io::Result<PathBuf> {
    let path = local_path(path)?;
    touch_file(&path)?;

    Ok(path)
}

pub fn read_file(path: &Path) -> io::Result<String> {
    let mut file   = File::open(path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;

    Ok(buffer)
}

pub fn lerp(v0: f32, v1: f32, t: f32) -> f32 {
    (1. - t) * v0 + t * v1
}<commit_msg>Return error when a file is empty<commit_after>#[macro_use] pub mod error;

use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::{self, Read, Error, ErrorKind};

pub fn local_path(path: &str) -> io::Result<PathBuf> {
    let mut base = ::std::env::current_exe()?;
    base.pop();
    base.push(path);
    Ok(base)
}

/// Creates a file only if it doesn't already exist and returns whether it was created or not.
pub fn touch_file(path: &Path) -> io::Result<bool> {
    let exists = path.exists();

    if !exists {
        File::create(path)?;
    }

    Ok(exists)
}

pub fn verify_local_file(path: &str) -> io::Result<PathBuf> {
    let path = local_path(path)?;
    touch_file(&path)?;

    Ok(path)
}

pub fn read_file(path: &Path) -> io::Result<String> {
    let mut file   = File::open(path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;

    if buffer.len() > 0 {
        Ok(buffer)
    } else {
        let path = path.to_str().ok_or(Error::new(
                        ErrorKind::InvalidData,
                        "util::read_file(): malformed path"))?;

        Err(Error::new(ErrorKind::InvalidData, format!("util::read_file(): {} is empty", path)))
    }
}

pub fn lerp(v0: f32, v1: f32, t: f32) -> f32 {
    (1. - t) * v0 + t * v1
}<|endoftext|>


<commit_before>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::expression::*;
use crate::query_builder::*;
use crate::query_dsl::RunQueryDsl;
use crate::result::QueryResult;
use crate::sql_types::{DieselNumericOps, SqlType};

#[derive(Debug, Clone, DieselNumericOps)]
#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// Returned by the [`sql()`] function.
///
/// [`sql()`]: ../dsl/fn.sql.html
pub struct SqlLiteral<ST, T = ()> {
    sql: String,
    inner: T,
    _marker: PhantomData<ST>,
}

impl<ST, T> SqlLiteral<ST, T>
where
    ST: TypedExpressionType,
{
    #[doc(hidden)]
    pub fn new(sql: String, inner: T) -> Self {
        SqlLiteral {
            sql: sql,
            inner: inner,
            _marker: PhantomData,
        }
    }

    /// Bind a value for use with this SQL query.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Text, Bool};
    /// #     let connection = establish_connection();
    /// let seans_id = users
    ///     .select(id)
    ///     .filter(sql::<Bool>("name = ").bind::<Text, _>("Sean"))
    ///     .get_result(&connection);
    /// assert_eq!(Ok(1), seans_id);
    ///
    /// let tess_id = sql::<Integer>("SELECT id FROM users WHERE name = ")
    ///     .bind::<Text, _>("Tess")
    ///     .get_result(&connection);
    /// assert_eq!(Ok(2), tess_id);
    /// # }
    /// ```
    ///
    /// ### Multiple Bind Params
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Text, Bool};
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > ")
    ///         .bind::<Integer,_>(1)
    ///         .sql(" AND name <> ")
    ///         .bind::<Text, _>("Ryan")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn bind<BindST, U>(self, bind_value: U) -> UncheckedBind<Self, U::Expression>
    where
        BindST: SqlType + TypedExpressionType,
        U: AsExpression<BindST>,
    {
        UncheckedBind::new(self, bind_value.as_expression())
    }

    /// Use literal SQL in the query builder
    ///
    /// This function is intended for use when you need a small bit of raw SQL in
    /// your query. If you want to write the entire query using raw SQL, use
    /// [`sql_query`](../fn.sql_query.html) instead.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::Bool;
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > 1")
    ///         .sql(" AND name <> 'Ryan'")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn sql(self, sql: &str) -> SqlLiteral<ST, Self> {
        SqlLiteral::new(sql.into(), self)
    }
}

impl<ST, T> Expression for SqlLiteral<ST, T>
where
    ST: TypedExpressionType,
{
    type SqlType = ST;
}

impl<ST, T, DB> QueryFragment<DB> for SqlLiteral<ST, T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);
        Ok(())
    }
}

impl<ST, T> QueryId for SqlLiteral<ST, T> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<ST, T> Query for SqlLiteral<ST, T>
where
    Self: Expression,
{
    type SqlType = ST;
}

impl<ST, T, Conn> RunQueryDsl<Conn> for SqlLiteral<ST, T> {}

impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> where Self: Expression {}

impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> where Self: Expression {}

impl<ST, T, GB> ValidGrouping<GB> for SqlLiteral<ST, T> {
    type IsAggregate = is_aggregate::Never;
}

/// Use literal SQL in the query builder.
///
/// Available for when you truly cannot represent something using the expression
/// DSL. You will need to provide the SQL type of the expression, in addition to
/// the SQL.
///
/// This function is intended for use when you need a small bit of raw SQL in
/// your query. If you want to write the entire query using raw SQL, use
/// [`sql_query`](../fn.sql_query.html) instead.
///
/// Query parameters can be bound into the literal SQL using [`SqlLiteral::bind()`].
///
/// # Safety
///
/// The compiler will be unable to verify the correctness of the annotated type.
/// If you give the wrong type, it'll either return an error when deserializing
/// the query result or produce unexpected values.
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # fn main() {
/// #     run_test_1().unwrap();
/// #     run_test_2().unwrap();
/// # }
/// #
/// # fn run_test_1() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     use diesel::sql_types::Bool;
/// use diesel::dsl::sql;
/// #     let connection = establish_connection();
/// let user = users.filter(sql::<Bool>("name = 'Sean'")).first(&connection)?;
/// let expected = (1, String::from("Sean"));
/// assert_eq!(expected, user);
/// #     Ok(())
/// # }
/// #
/// # fn run_test_2() -> QueryResult<()> {
/// #     use self::users::dsl::*;
/// #     use diesel::dsl::sql;
/// #     use diesel::sql_types::{Bool, Integer, Text};
/// #     let connection = establish_connection();
/// #     diesel::insert_into(users)
/// #         .values(name.eq("Jim"))
/// #         .execute(&connection).unwrap();
/// let query = users
///     .select(name)
///     .filter(
///         sql::<Bool>("id > ")
///         .bind::<Integer,_>(1)
///         .sql(" AND name <> ")
///         .bind::<Text, _>("Ryan")
///     )
///     .get_results(&connection);
/// let expected = vec!["Tess".to_string()];
/// assert_eq!(Ok(expected), query);
/// #     Ok(())
/// # }
/// ```
/// [`SqlLiteral::bind()`]: ../expression/struct.SqlLiteral.html#method.bind
pub fn sql<ST>(sql: &str) -> SqlLiteral<ST>
where
    ST: TypedExpressionType,
{
    SqlLiteral::new(sql.into(), ())
}

#[derive(QueryId, Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
///
/// [`SqlLiteral::bind()`]: ./struct.SqlLiteral.html#method.bind
pub struct UncheckedBind<Query, Value> {
    query: Query,
    value: Value,
}

impl<Query, Value> UncheckedBind<Query, Value>
where
    Query: Expression,
{
    pub(crate) fn new(query: Query, value: Value) -> Self {
        UncheckedBind { query, value }
    }

    /// Use literal SQL in the query builder.
    ///
    /// This function is intended for use when you need a small bit of raw SQL in
    /// your query. If you want to write the entire query using raw SQL, use
    /// [`sql_query`](../fn.sql_query.html) instead.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Bool};
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > ")
    ///         .bind::<Integer,_>(1)
    ///         .sql(" AND name <> 'Ryan'")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
        SqlLiteral::new(sql.into(), self)
    }
}

impl<Query, Value> Expression for UncheckedBind<Query, Value>
where
    Query: Expression,
{
    type SqlType = Query::SqlType;
}

impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
where
    DB: Backend,
    Query: QueryFragment<DB>,
    Value: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        self.value.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<Q, Value> Query for UncheckedBind<Q, Value>
where
    Q: Query,
{
    type SqlType = Q::SqlType;
}

impl<Query, Value, GB> ValidGrouping<GB> for UncheckedBind<Query, Value> {
    type IsAggregate = is_aggregate::Never;
}

impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
    Self: AppearsOnTable<QS>
{
}

impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}

impl<Query, Value, Conn> RunQueryDsl<Conn> for UncheckedBind<Query, Value> {}
<commit_msg>Fix warning raised by GitHub checks<commit_after>use std::marker::PhantomData;

use crate::backend::Backend;
use crate::expression::*;
use crate::query_builder::*;
use crate::query_dsl::RunQueryDsl;
use crate::result::QueryResult;
use crate::sql_types::{DieselNumericOps, SqlType};

#[derive(Debug, Clone, DieselNumericOps)]
#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// Returned by the [`sql()`] function.
///
/// [`sql()`]: ../dsl/fn.sql.html
pub struct SqlLiteral<ST, T = ()> {
    sql: String,
    inner: T,
    _marker: PhantomData<ST>,
}

impl<ST, T> SqlLiteral<ST, T>
where
    ST: TypedExpressionType,
{
    #[doc(hidden)]
    pub fn new(sql: String, inner: T) -> Self {
        SqlLiteral {
            sql: sql,
            inner: inner,
            _marker: PhantomData,
        }
    }

    /// Bind a value for use with this SQL query.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Text, Bool};
    /// #     let connection = establish_connection();
    /// let seans_id = users
    ///     .select(id)
    ///     .filter(sql::<Bool>("name = ").bind::<Text, _>("Sean"))
    ///     .get_result(&connection);
    /// assert_eq!(Ok(1), seans_id);
    ///
    /// let tess_id = sql::<Integer>("SELECT id FROM users WHERE name = ")
    ///     .bind::<Text, _>("Tess")
    ///     .get_result(&connection);
    /// assert_eq!(Ok(2), tess_id);
    /// # }
    /// ```
    ///
    /// ### Multiple Bind Params
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Text, Bool};
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > ")
    ///         .bind::<Integer,_>(1)
    ///         .sql(" AND name <> ")
    ///         .bind::<Text, _>("Ryan")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn bind<BindST, U>(self, bind_value: U) -> UncheckedBind<Self, U::Expression>
    where
        BindST: SqlType + TypedExpressionType,
        U: AsExpression<BindST>,
    {
        UncheckedBind::new(self, bind_value.as_expression())
    }

    /// Use literal SQL in the query builder
    ///
    /// This function is intended for use when you need a small bit of raw SQL in
    /// your query. If you want to write the entire query using raw SQL, use
    /// [`sql_query`](../fn.sql_query.html) instead.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::Bool;
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > 1")
    ///         .sql(" AND name <> 'Ryan'")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn sql(self, sql: &str) -> SqlLiteral<ST, Self> {
        SqlLiteral::new(sql.into(), self)
    }
}

impl<ST, T> Expression for SqlLiteral<ST, T>
where
    ST: TypedExpressionType,
{
    type SqlType = ST;
}

impl<ST, T, DB> QueryFragment<DB> for SqlLiteral<ST, T>
where
    DB: Backend,
    T: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();
        self.inner.walk_ast(out.reborrow())?;
        out.push_sql(&self.sql);
        Ok(())
    }
}

impl<ST, T> QueryId for SqlLiteral<ST, T> {
    type QueryId = ();

    const HAS_STATIC_QUERY_ID: bool = false;
}

impl<ST, T> Query for SqlLiteral<ST, T>
where
    Self: Expression,
{
    type SqlType = ST;
}

impl<ST, T, Conn> RunQueryDsl<Conn> for SqlLiteral<ST, T> {}

impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> where Self: Expression {}

impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> where Self: Expression {}

impl<ST, T, GB> ValidGrouping<GB> for SqlLiteral<ST, T> {
    type IsAggregate = is_aggregate::Never;
}

/// Use literal SQL in the query builder.
///
/// Available for when you truly cannot represent something using the expression
/// DSL. You will need to provide the SQL type of the expression, in addition to
/// the SQL.
///
/// This function is intended for use when you need a small bit of raw SQL in
/// your query. If you want to write the entire query using raw SQL, use
/// [`sql_query`](../fn.sql_query.html) instead.
///
/// Query parameters can be bound into the literal SQL using [`SqlLiteral::bind()`].
///
/// # Safety
///
/// The compiler will be unable to verify the correctness of the annotated type.
/// If you give the wrong type, it'll either return an error when deserializing
/// the query result or produce unexpected values.
///
/// # Examples
///
/// ```rust
/// # include!("../doctest_setup.rs");
/// # fn main() {
/// #     run_test_1().unwrap();
/// #     run_test_2().unwrap();
/// # }
/// #
/// # fn run_test_1() -> QueryResult<()> {
/// #     use schema::users::dsl::*;
/// #     use diesel::sql_types::Bool;
/// use diesel::dsl::sql;
/// #     let connection = establish_connection();
/// let user = users.filter(sql::<Bool>("name = 'Sean'")).first(&connection)?;
/// let expected = (1, String::from("Sean"));
/// assert_eq!(expected, user);
/// #     Ok(())
/// # }
/// #
/// # fn run_test_2() -> QueryResult<()> {
/// #     use crate::schema::users::dsl::*;
/// #     use diesel::dsl::sql;
/// #     use diesel::sql_types::{Bool, Integer, Text};
/// #     let connection = establish_connection();
/// #     diesel::insert_into(users)
/// #         .values(name.eq("Jim"))
/// #         .execute(&connection).unwrap();
/// let query = users
///     .select(name)
///     .filter(
///         sql::<Bool>("id > ")
///         .bind::<Integer,_>(1)
///         .sql(" AND name <> ")
///         .bind::<Text, _>("Ryan")
///     )
///     .get_results(&connection);
/// let expected = vec!["Tess".to_string()];
/// assert_eq!(Ok(expected), query);
/// #     Ok(())
/// # }
/// ```
/// [`SqlLiteral::bind()`]: ../expression/struct.SqlLiteral.html#method.bind
pub fn sql<ST>(sql: &str) -> SqlLiteral<ST>
where
    ST: TypedExpressionType,
{
    SqlLiteral::new(sql.into(), ())
}

#[derive(QueryId, Debug, Clone, Copy)]
#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
///
/// [`SqlLiteral::bind()`]: ./struct.SqlLiteral.html#method.bind
pub struct UncheckedBind<Query, Value> {
    query: Query,
    value: Value,
}

impl<Query, Value> UncheckedBind<Query, Value>
where
    Query: Expression,
{
    pub(crate) fn new(query: Query, value: Value) -> Self {
        UncheckedBind { query, value }
    }

    /// Use literal SQL in the query builder.
    ///
    /// This function is intended for use when you need a small bit of raw SQL in
    /// your query. If you want to write the entire query using raw SQL, use
    /// [`sql_query`](../fn.sql_query.html) instead.
    ///
    /// # Safety
    ///
    /// This function should be used with care, as Diesel cannot validate that
    /// the value is of the right type nor can it validate that you have passed
    /// the correct number of parameters.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #    users {
    /// #        id -> Integer,
    /// #        name -> VarChar,
    /// #    }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     use diesel::dsl::sql;
    /// #     use diesel::sql_types::{Integer, Bool};
    /// #     let connection = establish_connection();
    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
    /// #           .execute(&connection).unwrap();
    /// let query = users
    ///     .select(name)
    ///     .filter(
    ///         sql::<Bool>("id > ")
    ///         .bind::<Integer,_>(1)
    ///         .sql(" AND name <> 'Ryan'")
    ///     )
    ///     .get_results(&connection);
    /// let expected = vec!["Tess".to_string()];
    /// assert_eq!(Ok(expected), query);
    /// # }
    /// ```
    pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
        SqlLiteral::new(sql.into(), self)
    }
}

impl<Query, Value> Expression for UncheckedBind<Query, Value>
where
    Query: Expression,
{
    type SqlType = Query::SqlType;
}

impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
where
    DB: Backend,
    Query: QueryFragment<DB>,
    Value: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        self.query.walk_ast(out.reborrow())?;
        self.value.walk_ast(out.reborrow())?;
        Ok(())
    }
}

impl<Q, Value> Query for UncheckedBind<Q, Value>
where
    Q: Query,
{
    type SqlType = Q::SqlType;
}

impl<Query, Value, GB> ValidGrouping<GB> for UncheckedBind<Query, Value> {
    type IsAggregate = is_aggregate::Never;
}

impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
    Self: AppearsOnTable<QS>
{
}

impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}

impl<Query, Value, Conn> RunQueryDsl<Conn> for UncheckedBind<Query, Value> {}
<|endoftext|>