///|
/// Represents a vCard property.
pub struct Property {
name : String
types : Array[String]
value : String
} derive(Show, Eq, ToJson)
///|
/// Represents a complete vCard.
pub struct VCard {
properties : Array[Property]
} derive(Show, Eq, ToJson)
///|
pub fn VCard::new() -> VCard {
let properties = [
Property::{
name: "VERSION".to_string(),
types: [],
value: "3.0".to_string(),
},
]
VCard::{ properties, }
}
///|
pub fn VCard::add_property(
self : VCard,
name : String,
types : Array[String],
value : String,
) -> VCard {
let properties = self.properties
properties.push(Property::{ name, types, value })
VCard::{ properties, }
}
///|
pub fn VCard::get_property(self : VCard, name : String) -> Property? {
for prop in self.properties {
if prop.name == name {
return Some(prop)
}
}
None
}
///|
pub fn VCard::get_property_value(self : VCard, name : String) -> String? {
for prop in self.properties {
if prop.name == name {
return Some(prop.value)
}
}
None
}
///|
pub fn VCard::stringify(self : VCard) -> String {
let lines = Array::new()
lines.push("BEGIN:VCARD")
for prop in self.properties {
let types = prop.types.join(";")
if types.is_empty() {
lines.push(prop.name + ":" + prop.value)
} else {
lines.push(prop.name + ";" + types + ":" + prop.value)
}
}
lines.push("END:VCARD")
lines.join("\n")
}
///|
pub fn VCard::validate(self : VCard) -> Result[VCard, String] {
// Validate required properties
let mut has_version = false
let mut has_fn = false
let mut has_n = false
for prop in self.properties {
println("Checking property: \{prop.name}")
if prop.name == "VERSION" {
has_version = true
}
if prop.name == "FN" {
has_fn = true
}
if prop.name == "N" {
has_n = true
}
}
if !has_version {
return Err("Missing VERSION property")
}
if !has_fn {
return Err("Missing FN property")
}
if !has_n {
return Err("Missing N property")
}
Ok(self)
}
///|
pub fn VCard::parse(input : String) -> Result[VCard, String] {
let lines = input.split("\n").map(fn(s) { s.trim() })
let properties = Array::new()
let mut in_vcard = false
let mut vcard_count = 0
for line in lines {
if line.is_empty() {
continue
}
println("LINE: \{line}")
if line.contains(":") {
match line.split(":").to_array() {
["BEGIN", "VCARD"] => {
if in_vcard {
return Err("Multiple vCards found")
}
in_vcard = true
vcard_count = vcard_count + 1
println("BEGIN VCARD")
}
["END", "VCARD"] => {
if !in_vcard {
return Err("Unexpected END VCARD")
}
in_vcard = false
}
["VERSION", version_value] =>
if version_value != "3.0" {
return Err("Unsupported vCard version: \{version_value}")
} else {
properties.push(Property::{
name: "VERSION".to_string(),
types: [],
value: version_value.to_string(),
})
}
[name_type, value] => {
println("ddt \{name_type}")
println(name_type.split(";"))
match name_type.split(";").to_array() {
[name, .. vals] => {
let types = vals.map(fn(s) { s.to_string() })
properties.push(Property::{
name: name.to_string(),
types,
value: value.to_string(),
})
}
_ => continue
}
}
_ => continue
}
} else {
continue
}
}
if vcard_count == 0 {
return Err("No vCard found")
}
if in_vcard {
return Err("Missing END:VCARD")
}
let vcard = VCard::{ properties, }
if vcard.validate() is Err(e) {
return Err("vCard validation failed \{e}")
}
Ok(vcard)
}
///|
pub struct Contacts {
vcards : Array[VCard]
}
///|
pub fn Contacts::new() -> Contacts {
Contacts::{ vcards: Array::new() }
}
///|
pub fn Contacts::add_vcard(self : Contacts, vcard : VCard) -> Contacts {
self.vcards.push(vcard)
self
}
///|
pub fn Contacts::stringify(self : Contacts) -> String {
let vcard_strings = self.vcards.map(fn(vcard) { vcard.stringify() })
vcard_strings.join("\n")
}
// -----------------------------------------------------------
///|
pub fn fib(n : Int) -> Int64 {
loop (n, 0L, 1L) {
(0, _, b) => b
(i, a, b) => continue (i - 1, b, a + b)
}
}
///|
/// data is a labelled argument without default value having type Array[Int]
/// start is an optional labelled argument with default value 0 having type Int
/// length is an optional labelled argument without default value having type Option[Int]
pub fn sum(data~ : Array[Int], start? : Int = 0, length? : Int) -> Int {
let end = if length is Some(length) { start + length } else { data.length() }
for i = start, sum = 0; i < end; i = i + 1, sum = sum + data[i] {
} else {
sum
}
}