1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! Contract interface.

use serde_json;
use super::{Operation, Constructor, Function, Event};
use errors::Error;

/// Contract interface.
#[derive(Clone, Debug, PartialEq, Deserialize)]
pub struct Interface(Vec<Operation>);

impl Interface {
	/// Loads interface from json.
	pub fn load(bytes: &[u8]) -> Result<Self, Error> {
		serde_json::from_slice(bytes).map_err(From::from)
	}

	/// Returns contract constructor specification.
	// TODO: these methods can be removed in a future major version as they are
	//       currently unused and the same functionality can be achieved with
	//       Contract
	pub fn constructor(&self) -> Option<Constructor> {
		self.0.iter()
			.filter_map(Operation::constructor)
			.next()
			.cloned()
	}

	/// Returns specification of contract function.
	pub fn function(&self, name: String) -> Option<Function> {
		self.0.iter()
			.filter_map(Operation::function)
			.find(|f| f.name == name)
			.cloned()
	}

	/// Returns specification of contract event.
	pub fn event(&self, name: String) -> Option<Event> {
		self.0.iter()
			.filter_map(Operation::event)
			.find(|e| e.name == name)
			.cloned()
	}

	/// Get an iterator over all operations of the contract.
	pub fn operations(&self) -> Operations {
		Operations {
			inner: self.0.iter()
		}
	}
}

/// An iterator over all operations of an interface.
pub struct Operations<'a> {
	inner: ::std::slice::Iter<'a, Operation>,
}

impl<'a> Iterator for Operations<'a> {
	type Item = &'a Operation;

	fn next(&mut self) -> Option<&'a Operation> {
		self.inner.next()
	}
}

#[cfg(test)]
mod tests {
	use serde_json;
	use super::Interface;
	use spec::{ParamType, Function, Param, Operation, Event, EventParam};

	#[test]
	fn deserialize_interface() {
		let s = r#"[{
			"type":"event",
			"inputs": [{
				"name":"a",
				"type":"uint256",
				"indexed":true
			},{
				"name":"b",
				"type":"bytes32",
				"indexed":false
			}],
			"name":"Event2",
			"anonymous": false
		}, {
			"type":"function",
			"inputs": [{
				"name":"a",
				"type":"uint256"
			}],
			"name":"foo",
			"outputs": []
		}]"#;

		let deserialized: Interface = serde_json::from_str(s).unwrap();

		assert_eq!(deserialized, Interface(vec![
			Operation::Event(Event {
				name: "Event2".to_owned(),
				inputs: vec![
					EventParam {
						name: "a".to_owned(),
						kind: ParamType::Uint(256),
						indexed: true,
					},
					EventParam {
						name: "b".to_owned(),
						kind: ParamType::FixedBytes(32),
						indexed: false,
					}
				],
				anonymous: false,
			}),
			Operation::Function(Function {
				name: "foo".to_owned(),
				inputs: vec![
					Param {
						name: "a".to_owned(),
						kind: ParamType::Uint(256),
					}
				],
				outputs: vec![]
			})
		]));
	}

	#[test]
	fn deserialize_event2() {
		let s = r#"[{
			"inputs": [{
				"name": "_curator",
				"type": "address"
			}, {
				"name": "_daoCreator",
				"type": "address"
			}, {
				"name": "_proposalDeposit",
				"type": "uint256"
			}, {
				"name": "_minTokensToCreate",
				"type": "uint256"
			}, {
				"name": "_closingTime",
				"type": "uint256"
			}, {
				"name": "_privateCreation",
				"type": "address"
			}],
			"type": "constructor"
		}]"#;

		let _: Interface = serde_json::from_str(s).unwrap();

	}
}