Skip to content

Commit ae6d27c

Browse files
committed
upper-case and lower-case
1 parent 73cec63 commit ae6d27c

File tree

9 files changed

+325
-111
lines changed

9 files changed

+325
-111
lines changed

src/clojure_string.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
pub (crate) mod reverse;
2-
pub (crate) mod join;
3-
pub (crate) mod blank_qmark_;
1+
pub(crate) mod blank_qmark_;
2+
pub(crate) mod join;
3+
pub(crate) mod lower_case;
4+
pub(crate) mod reverse;
5+
pub(crate) mod upper_case;

src/clojure_string/blank_qmark_.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@ impl IFn for BlankFn {
2424
if s.len() == 0 {
2525
Value::Boolean(true)
2626
} else {
27-
return Value::Boolean(s.chars().filter(|c| !c.is_whitespace()).collect::<Vec<char>>().len() == 0)
27+
return Value::Boolean(
28+
s.chars()
29+
.filter(|c| !c.is_whitespace())
30+
.collect::<Vec<char>>()
31+
.len()
32+
== 0,
33+
);
2834
}
2935
}
3036
Value::String(s) => Value::String(s.chars().rev().collect()),
31-
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value())
37+
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value()),
3238
}
3339
}
3440
}
@@ -37,10 +43,10 @@ impl IFn for BlankFn {
3743
#[cfg(test)]
3844
mod tests {
3945
mod reverse_tests {
40-
use crate::value::Value;
41-
use std::rc::Rc;
4246
use crate::clojure_string::blank_qmark_::BlankFn;
4347
use crate::ifn::IFn;
48+
use crate::value::Value;
49+
use std::rc::Rc;
4450

4551
#[test]
4652
fn is_non_empty_string_blank() {
@@ -81,4 +87,4 @@ mod tests {
8187
assert_eq!(Value::Boolean(true), blank.invoke(args));
8288
}
8389
}
84-
}
90+
}

src/clojure_string/join.rs

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ use crate::value::{ToValue, Value};
33
use std::rc::Rc;
44

55
use crate::error_message;
6-
use crate::type_tag::TypeTag;
6+
use crate::persistent_list::PersistentList::Cons;
77
use crate::persistent_list::ToPersistentListIter;
88
use crate::persistent_vector::ToPersistentVectorIter;
9+
use crate::type_tag::TypeTag;
910
use itertools::Itertools;
10-
use crate::persistent_list::PersistentList::Cons;
1111

1212
/// clojure.string/join ; joins a coll of items together as a string
1313
/// (join
1414
/// [coll]
15-
/// [separator coll])
15+
/// [separator coll])
1616
#[derive(Debug, Clone)]
1717
pub struct JoinFn {}
1818
impl ToValue for JoinFn {
@@ -25,8 +25,14 @@ impl IFn for JoinFn {
2525
if args.len() == 1 || args.len() == 2 {
2626
let separator = if args.len() == 2 {
2727
args.get(0).unwrap().to_string()
28-
} else { String::from("") };
29-
let coll = if args.len() == 1 { args.get(0) } else { args.get(1) };
28+
} else {
29+
String::from("")
30+
};
31+
let coll = if args.len() == 1 {
32+
args.get(0)
33+
} else {
34+
args.get(1)
35+
};
3036
match coll.unwrap().to_value() {
3137
Value::PersistentList(Cons(head, tail, count)) => {
3238
return if count == 0 {
@@ -35,47 +41,55 @@ impl IFn for JoinFn {
3541
Value::String(head.to_string())
3642
} else {
3743
Value::String(
38-
String::from(
39-
head.to_string()) + separator.as_str() +
40-
tail.iter()
41-
.map(|x| x.to_string())
42-
.collect::<Vec<std::string::String>>()
43-
.join(&separator).as_str())
44+
String::from(head.to_string())
45+
+ separator.as_str()
46+
+ tail
47+
.iter()
48+
.map(|x| x.to_string())
49+
.collect::<Vec<std::string::String>>()
50+
.join(&separator)
51+
.as_str(),
52+
)
4453
}
45-
},
54+
}
4655
Value::PersistentVector(pvec) => {
4756
return if pvec.vals.len() == 0 {
4857
Value::String(String::from(""))
4958
} else {
5059
Value::String(String::from(
51-
pvec.vals.iter()
60+
pvec.vals
61+
.iter()
5262
.map(|x| x.to_string())
5363
.collect::<Vec<std::string::String>>()
54-
.join(&separator).as_str()))
64+
.join(&separator)
65+
.as_str(),
66+
))
5567
}
5668
}
57-
_ => Value::String(String::from(""))
69+
_ => Value::String(String::from("")),
5870
}
5971
} else {
60-
return error_message::wrong_varg_count(&[1,2], args.len());
72+
return error_message::wrong_varg_count(&[1, 2], args.len());
6173
}
6274
}
6375
}
6476

6577
#[cfg(test)]
6678
mod tests {
6779
mod reverse_tests {
68-
use crate::value::Value;
69-
use std::rc::Rc;
7080
use crate::clojure_string::join::JoinFn;
7181
use crate::ifn::IFn;
7282
use crate::persistent_list::PersistentList;
7383
use crate::persistent_vector::PersistentVector;
84+
use crate::value::Value;
85+
use std::rc::Rc;
7486

7587
#[test]
7688
fn join_empty_collection_to_empty_string() {
7789
let join = JoinFn {};
78-
let args = vec![Rc::new(Value::PersistentList(vec![].into_iter().collect::<PersistentList>()))];
90+
let args = vec![Rc::new(Value::PersistentList(
91+
vec![].into_iter().collect::<PersistentList>(),
92+
))];
7993
assert_eq!(Value::String(String::from("")), join.invoke(args));
8094
}
8195

@@ -84,7 +98,10 @@ mod tests {
8498
let join = JoinFn {};
8599
let s = "hello";
86100
let args = vec![Rc::new(Value::PersistentList(
87-
vec![Rc::new(Value::String(String::from(s)))].into_iter().collect::<PersistentList>()))];
101+
vec![Rc::new(Value::String(String::from(s)))]
102+
.into_iter()
103+
.collect::<PersistentList>(),
104+
))];
88105
assert_eq!(Value::String(String::from("hello")), join.invoke(args));
89106
}
90107

@@ -93,37 +110,62 @@ mod tests {
93110
let join = JoinFn {};
94111
let s = "hello";
95112
let args = vec![Rc::new(Value::PersistentList(
96-
vec![Rc::new(Value::String(String::from(s))),
97-
Rc::new(Value::I32(5)),
98-
Rc::new(Value::String(String::from(s)))]
99-
.into_iter().collect::<PersistentList>()))];
100-
assert_eq!(Value::String(String::from("hello5hello")), join.invoke(args));
113+
vec![
114+
Rc::new(Value::String(String::from(s))),
115+
Rc::new(Value::I32(5)),
116+
Rc::new(Value::String(String::from(s))),
117+
]
118+
.into_iter()
119+
.collect::<PersistentList>(),
120+
))];
121+
assert_eq!(
122+
Value::String(String::from("hello5hello")),
123+
join.invoke(args)
124+
);
101125
}
102126

103127
#[test]
104128
fn join_multiple_items_in_collection_with_separator_to_string() {
105129
let join = JoinFn {};
106130
let s = "hello";
107-
let args = vec![Rc::new(Value::String(String::from(", "))),
108-
Rc::new(Value::PersistentList(
109-
vec![Rc::new(Value::String(String::from(s))),
110-
Rc::new(Value::I32(5)),
111-
Rc::new(Value::String(String::from(s)))]
112-
.into_iter().collect::<PersistentList>()))];
113-
assert_eq!(Value::String(String::from("hello, 5, hello")), join.invoke(args));
131+
let args = vec![
132+
Rc::new(Value::String(String::from(", "))),
133+
Rc::new(Value::PersistentList(
134+
vec![
135+
Rc::new(Value::String(String::from(s))),
136+
Rc::new(Value::I32(5)),
137+
Rc::new(Value::String(String::from(s))),
138+
]
139+
.into_iter()
140+
.collect::<PersistentList>(),
141+
)),
142+
];
143+
assert_eq!(
144+
Value::String(String::from("hello, 5, hello")),
145+
join.invoke(args)
146+
);
114147
}
115148

116149
#[test]
117150
fn join_multiple_items_in_pvec_collection_with_separator_to_string() {
118151
let join = JoinFn {};
119152
let s = "hello";
120-
let args = vec![Rc::new(Value::String(String::from(", "))),
121-
Rc::new(Value::PersistentVector(
122-
vec![Rc::new(Value::String(String::from(s))),
123-
Rc::new(Value::I32(5)),
124-
Rc::new(Value::String(String::from(s)))]
125-
.into_iter().collect::<PersistentVector>()))];
126-
assert_eq!(Value::String(String::from("hello, 5, hello")), join.invoke(args));
153+
let args = vec![
154+
Rc::new(Value::String(String::from(", "))),
155+
Rc::new(Value::PersistentVector(
156+
vec![
157+
Rc::new(Value::String(String::from(s))),
158+
Rc::new(Value::I32(5)),
159+
Rc::new(Value::String(String::from(s))),
160+
]
161+
.into_iter()
162+
.collect::<PersistentVector>(),
163+
)),
164+
];
165+
assert_eq!(
166+
Value::String(String::from("hello, 5, hello")),
167+
join.invoke(args)
168+
);
127169
}
128170
}
129-
}
171+
}

src/clojure_string/lower_case.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{ToValue, Value};
3+
use std::rc::Rc;
4+
5+
use crate::error_message;
6+
use crate::type_tag::TypeTag;
7+
8+
/// clojure.string/upper-case ; converts characters to uppercase
9+
#[derive(Debug, Clone)]
10+
pub struct LowerCaseFn {}
11+
impl ToValue for LowerCaseFn {
12+
fn to_value(&self) -> Value {
13+
Value::IFn(Rc::new(self.clone()))
14+
}
15+
}
16+
impl IFn for LowerCaseFn {
17+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
18+
if args.len() != 1 {
19+
return error_message::wrong_arg_count(1, args.len());
20+
} else {
21+
match args.get(0).unwrap().to_value() {
22+
Value::String(s) => Value::String(s.to_lowercase()),
23+
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value()),
24+
}
25+
}
26+
}
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
mod reverse_tests {
32+
use crate::clojure_string::lower_case::LowerCaseFn;
33+
use crate::ifn::IFn;
34+
use crate::value::Value;
35+
use std::rc::Rc;
36+
37+
#[test]
38+
fn reverse_string() {
39+
let reverse = LowerCaseFn {};
40+
let s = "1.2.3 HELLO";
41+
let args = vec![Rc::new(Value::String(String::from(s)))];
42+
assert_eq!(
43+
Value::String(String::from("1.2.3 hello")),
44+
reverse.invoke(args)
45+
);
46+
}
47+
}
48+
}

src/clojure_string/reverse.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ impl IFn for ReverseFn {
2020
} else {
2121
match args.get(0).unwrap().to_value() {
2222
Value::String(s) => Value::String(s.chars().rev().collect()),
23-
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value())
23+
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value()),
2424
}
2525
}
2626
}
@@ -29,10 +29,10 @@ impl IFn for ReverseFn {
2929
#[cfg(test)]
3030
mod tests {
3131
mod reverse_tests {
32-
use crate::value::Value;
33-
use std::rc::Rc;
3432
use crate::clojure_string::reverse::ReverseFn;
3533
use crate::ifn::IFn;
34+
use crate::value::Value;
35+
use std::rc::Rc;
3636

3737
#[test]
3838
fn reverse_string() {
@@ -42,4 +42,4 @@ mod tests {
4242
assert_eq!(Value::String(String::from("olleh")), reverse.invoke(args));
4343
}
4444
}
45-
}
45+
}

src/clojure_string/upper_case.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{ToValue, Value};
3+
use std::rc::Rc;
4+
5+
use crate::error_message;
6+
use crate::type_tag::TypeTag;
7+
8+
/// clojure.string/upper-case ; converts characters to uppercase
9+
#[derive(Debug, Clone)]
10+
pub struct UpperCaseFn {}
11+
impl ToValue for UpperCaseFn {
12+
fn to_value(&self) -> Value {
13+
Value::IFn(Rc::new(self.clone()))
14+
}
15+
}
16+
impl IFn for UpperCaseFn {
17+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
18+
if args.len() != 1 {
19+
return error_message::wrong_arg_count(1, args.len());
20+
} else {
21+
match args.get(0).unwrap().to_value() {
22+
Value::String(s) => Value::String(s.to_uppercase()),
23+
_a => error_message::type_mismatch(TypeTag::String, &_a.to_value()),
24+
}
25+
}
26+
}
27+
}
28+
29+
#[cfg(test)]
30+
mod tests {
31+
mod reverse_tests {
32+
use crate::clojure_string::upper_case::UpperCaseFn;
33+
use crate::ifn::IFn;
34+
use crate::value::Value;
35+
use std::rc::Rc;
36+
37+
#[test]
38+
fn reverse_string() {
39+
let reverse = UpperCaseFn {};
40+
let s = "1.2.3 hello";
41+
let args = vec![Rc::new(Value::String(String::from(s)))];
42+
assert_eq!(
43+
Value::String(String::from("1.2.3 HELLO")),
44+
reverse.invoke(args)
45+
);
46+
}
47+
}
48+
}

0 commit comments

Comments
 (0)