Skip to content

Commit de57e31

Browse files
committed
add index map
1 parent 4fa32c5 commit de57e31

File tree

10 files changed

+194
-48
lines changed

10 files changed

+194
-48
lines changed

lib/src/context.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,37 @@ use crate::http::Request;
22
use crate::http::Response;
33
use crate::http::Time;
44
use crate::Expr;
5+
use crate::Map;
56
use crate::Value;
6-
use std::collections::HashMap;
77
use std::fmt::Display;
88
use std::fmt::Formatter;
99
use std::fmt::Result;
1010

1111
#[derive(Default)]
1212
pub struct Context {
13-
inner: HashMap<String, Value>,
14-
requests: HashMap<String, (String, Vec<Expr>)>,
13+
inner: Map<String, Value>,
14+
requests: Map<String, (String, Vec<Expr>)>,
1515
records: Vec<Record>,
1616
}
1717

1818
impl Context {
1919
pub fn new() -> Self {
2020
Self {
21-
inner: HashMap::new(),
22-
requests: HashMap::new(),
21+
inner: Map::new(),
22+
requests: Map::new(),
2323
records: Vec::new(),
2424
}
2525
}
2626

27-
pub fn from(inner: HashMap<String, Value>) -> Self {
27+
pub fn from(inner: Map<String, Value>) -> Self {
2828
Self {
2929
inner,
30-
requests: HashMap::new(),
30+
requests: Map::new(),
3131
records: Vec::new(),
3232
}
3333
}
3434

35-
pub fn extend(&mut self, requests: HashMap<String, (String, Vec<Expr>)>) {
35+
pub fn extend(&mut self, requests: Map<String, (String, Vec<Expr>)>) {
3636
self.requests.extend(requests);
3737
}
3838

@@ -52,7 +52,7 @@ impl Context {
5252
self.records.push(record);
5353
}
5454

55-
pub fn into_map(self) -> HashMap<String, Value> {
55+
pub fn into_map(self) -> Map<String, Value> {
5656
self.inner
5757
}
5858

lib/src/evaluator.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use crate::Assert;
44
use crate::Context;
55
use crate::Expr;
66
use crate::Kind;
7+
use crate::Map;
78
use crate::Record;
89
use crate::Token;
910
use crate::Value;
10-
use std::collections::HashMap;
1111

1212
async fn eval_expr(expr: &Expr, context: &mut Context) -> Result<Value, String> {
1313
match expr {
@@ -50,7 +50,7 @@ async fn eval_array_literal(items: &[Expr], context: &mut Context) -> Result<Val
5050
}
5151

5252
async fn eval_map_literal(pairs: &Vec<(Expr, Expr)>, context: &mut Context) -> Result<Value, String> {
53-
let mut map = HashMap::new();
53+
let mut map = Map::new();
5454
for (key, value) in pairs {
5555
let key = eval_expr(key, context).await?;
5656
let value = eval_expr(value, context).await?;
@@ -248,11 +248,11 @@ async fn eval_list(items: &[Expr], context: &mut Context) -> Result<Vec<Value>,
248248
#[cfg(test)]
249249
mod tests {
250250
use super::eval_block;
251-
use crate::parser::Parser;
252-
use crate::parser::Source;
253251
use crate::Context;
252+
use crate::Map;
253+
use crate::Parser;
254+
use crate::Source;
254255
use crate::Value;
255-
use std::collections::HashMap;
256256

257257
async fn run_eval_tests(tests: Vec<(&str, Value)>) {
258258
for (text, expect) in tests {
@@ -423,17 +423,17 @@ mod tests {
423423
#[tokio::test]
424424
async fn test_map_literal() {
425425
let tests = vec![
426-
("{}", Value::Map(HashMap::new())),
426+
("{}", Value::Map(Map::new())),
427427
(
428428
"{1: 2, 2: 3}",
429-
Value::Map(HashMap::from_iter(vec![
429+
Value::Map(Map::from_iter(vec![
430430
(String::from("1"), Value::Integer(2)),
431431
(String::from("2"), Value::Integer(3)),
432432
])),
433433
),
434434
(
435435
"{1 + 1: 2 * 2, 3 + 3: 4 * 4}",
436-
Value::Map(HashMap::from_iter(vec![
436+
Value::Map(Map::from_iter(vec![
437437
(String::from("2"), Value::Integer(4)),
438438
(String::from("6"), Value::Integer(16)),
439439
])),

lib/src/http/response.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use super::Headers;
22
use super::Stream;
3+
use crate::Map;
34
use crate::Parser;
45
use crate::Source;
56
use crate::Value;
6-
use std::collections::HashMap;
77
use tokio::io::AsyncBufReadExt;
88
use tokio::io::AsyncReadExt;
99
use tokio::io::BufReader;
@@ -75,12 +75,12 @@ impl Response {
7575
})
7676
}
7777

78-
pub fn to_map(&self) -> HashMap<String, Value> {
79-
let mut map = HashMap::new();
78+
pub fn to_map(&self) -> Map<String, Value> {
79+
let mut map = Map::new();
8080
map.insert(String::from("version"), Value::String(self.version.to_string()));
8181
map.insert(String::from("status"), Value::Integer(self.status as i64));
8282
map.insert(String::from("reason"), Value::String(self.reason.to_string()));
83-
let mut headers: HashMap<String, Value> = HashMap::new();
83+
let mut headers = Map::new();
8484
for header in self.headers.iter() {
8585
match headers.get_mut(&header.name) {
8686
Some(Value::Array(array)) => array.push(Value::String(header.value.to_string())),
@@ -129,7 +129,7 @@ Access-Control-Allow-Credentials: true
129129
assert_eq!(7, response.headers.len());
130130
assert_eq!("{\n \"origin\": \"122.9.3.166\"\n}\n", response.body);
131131
assert_eq!(
132-
Some(&Value::Map(HashMap::from_iter(vec![(
132+
Some(&Value::Map(Map::from_iter(vec![(
133133
String::from("origin"),
134134
Value::String(String::from("122.9.3.166"))
135135
)]))),
@@ -159,7 +159,7 @@ Access-Control-Allow-Credentials: true
159159
assert_eq!(7, response.headers.len());
160160
assert_eq!("{\n \"origin\": \"122.9.3.166\"\n}\n", response.body);
161161
assert_eq!(
162-
Some(&Value::Map(HashMap::from_iter(vec![(
162+
Some(&Value::Map(Map::from_iter(vec![(
163163
String::from("origin"),
164164
Value::String(String::from("122.9.3.166"))
165165
)]))),

lib/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod context;
22
mod evaluator;
33
mod http;
44
mod lexer;
5+
mod map;
56
mod native;
67
mod parser;
78
mod stat;
@@ -12,6 +13,7 @@ mod writer;
1213

1314
use context::Assert;
1415
use context::Record;
16+
use map::Map;
1517
use syntax::Expr;
1618
use token::Kind;
1719
use token::Token;

lib/src/map.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
use std::borrow::Borrow;
2+
use std::collections::HashMap;
3+
use std::hash::Hash;
4+
5+
#[derive(Clone, Debug, PartialEq, Eq)]
6+
pub struct Map<K: Eq + Hash, V> {
7+
indices: HashMap<K, usize>,
8+
entries: Vec<V>,
9+
}
10+
11+
impl<K: Eq + Hash, V: Default> Map<K, V> {
12+
pub fn new() -> Self {
13+
Self::default()
14+
}
15+
16+
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
17+
match self.indices.get(&k) {
18+
Some(i) => {
19+
self.entries.push(v);
20+
Some(self.entries.swap_remove(*i))
21+
}
22+
None => {
23+
self.indices.insert(k, self.entries.len());
24+
self.entries.push(v);
25+
None
26+
}
27+
}
28+
}
29+
30+
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
31+
where
32+
K: Borrow<Q>,
33+
Q: Hash + Eq + ?Sized,
34+
{
35+
match self.indices.remove(k) {
36+
Some(i) => {
37+
self.entries.push(V::default());
38+
Some(self.entries.swap_remove(i))
39+
}
40+
None => None,
41+
}
42+
}
43+
44+
pub fn get<Q>(&self, k: &Q) -> Option<&V>
45+
where
46+
K: Borrow<Q>,
47+
Q: Hash + Eq + ?Sized,
48+
{
49+
match self.indices.get(k) {
50+
Some(i) => self.entries.get(*i),
51+
None => None,
52+
}
53+
}
54+
55+
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
56+
where
57+
K: Borrow<Q>,
58+
Q: Hash + Eq + ?Sized,
59+
{
60+
match self.indices.get(k) {
61+
Some(i) => self.entries.get_mut(*i),
62+
None => None,
63+
}
64+
}
65+
66+
pub fn iter(&self) -> Iter<K, V> {
67+
Iter {
68+
indices: self.indices.iter(),
69+
entries: &self.entries,
70+
}
71+
}
72+
73+
pub fn is_empty(&self) -> bool {
74+
self.indices.is_empty()
75+
}
76+
77+
pub fn len(&self) -> usize {
78+
self.indices.len()
79+
}
80+
81+
pub fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
82+
for (k, v) in iter {
83+
self.insert(k, v);
84+
}
85+
}
86+
}
87+
88+
impl<K: Eq + Hash, V> Default for Map<K, V> {
89+
fn default() -> Self {
90+
Self {
91+
indices: HashMap::default(),
92+
entries: Vec::default(),
93+
}
94+
}
95+
}
96+
97+
impl<K: Eq + Hash, V: Default> FromIterator<(K, V)> for Map<K, V> {
98+
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
99+
let mut map = Map::default();
100+
for (key, value) in iter {
101+
map.insert(key, value);
102+
}
103+
map
104+
}
105+
}
106+
107+
impl<K: Eq + Hash, V: Default> IntoIterator for Map<K, V> {
108+
type Item = (K, V);
109+
type IntoIter = IntoIter<K, V>;
110+
111+
fn into_iter(self) -> Self::IntoIter {
112+
IntoIter {
113+
indices: self.indices.into_iter(),
114+
entries: self.entries,
115+
}
116+
}
117+
}
118+
119+
pub struct IntoIter<K, V> {
120+
indices: std::collections::hash_map::IntoIter<K, usize>,
121+
entries: Vec<V>,
122+
}
123+
124+
impl<K, V: Default> Iterator for IntoIter<K, V> {
125+
type Item = (K, V);
126+
127+
fn next(&mut self) -> Option<Self::Item> {
128+
let (k, i) = self.indices.next()?;
129+
self.entries.push(V::default());
130+
let v = self.entries.swap_remove(i);
131+
Some((k, v))
132+
}
133+
}
134+
135+
pub struct Iter<'a, K, V> {
136+
indices: std::collections::hash_map::Iter<'a, K, usize>,
137+
entries: &'a [V],
138+
}
139+
140+
impl<'a, K, V> Iterator for Iter<'a, K, V> {
141+
type Item = (&'a K, &'a V);
142+
143+
fn next(&mut self) -> Option<Self::Item> {
144+
let (k, &i) = self.indices.next()?;
145+
self.entries.get(i).map(|v| (k, v))
146+
}
147+
}

lib/src/parser.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::lexer;
22
use crate::Expr;
33
use crate::Kind;
4+
use crate::Map;
45
use crate::Token;
5-
use std::collections::HashMap;
66

77
pub struct Source {
88
pub exprs: Vec<Expr>,
9-
pub requests: HashMap<String, (String, Vec<Expr>)>,
10-
pub tests: HashMap<String, Vec<Expr>>,
9+
pub requests: Map<String, (String, Vec<Expr>)>,
10+
pub tests: Map<String, Vec<Expr>>,
1111
}
1212

1313
pub struct Parser {
@@ -67,8 +67,8 @@ impl Parser {
6767

6868
pub fn parse(&mut self) -> Result<Source, String> {
6969
let mut exprs = Vec::new();
70-
let mut requests = HashMap::new();
71-
let mut tests = HashMap::new();
70+
let mut requests = Map::new();
71+
let mut tests = Map::new();
7272
while self.current_token().kind != Kind::Eof {
7373
match self.current_token().kind {
7474
Kind::Request => {

0 commit comments

Comments
 (0)