1use crate::parse::{findattr, getcfgbase};
2use rnix::{SyntaxKind, SyntaxNode};
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum ReadError {
7 #[error("Error while parsing")]
8 ParseError,
9 #[error("No attributes")]
10 NoAttr,
11 #[error("Error with array")]
12 ArrayError,
13}
14
15pub fn readvalue(f: &str, query: &str) -> Result<String, ReadError> {
16 let ast = rnix::Root::parse(f);
17 let configbase = match getcfgbase(&ast.syntax()) {
18 Some(x) => x,
19 None => {
20 return Err(ReadError::ParseError);
21 }
22 };
23 let outnode = match findattr(&configbase, query) {
24 Some(x) => {
25 match findvalue(&x) {
26 Some(y) => y.to_string(),
27 None => return Err(ReadError::NoAttr),
28 }
29 }
30 None => return Err(ReadError::NoAttr),
31 };
32 Ok(outnode.trim().to_string())
33}
34
35pub fn findvalue(node: &SyntaxNode) -> Option<SyntaxNode> {
36 for child in node.children() {
38 if child.kind() != SyntaxKind::NODE_ATTRPATH {
39 let x =
40 Some(rnix::Root::parse(&nixpkgs_fmt::reformat_string(&child.to_string())).syntax());
41 return x;
42 }
43 }
44 None
45}
46
47pub fn getarrvals(f: &str, query: &str) -> Result<Vec<String>, ReadError> {
48 let ast = rnix::Root::parse(f);
49 let configbase = match getcfgbase(&ast.syntax()) {
50 Some(x) => x,
51 None => {
52 return Err(ReadError::ParseError);
53 }
54 };
55 let output = match findattr(&configbase, query) {
56 Some(x) => match getarrvals_aux(&x) {
57 Some(y) => y,
58 None => return Err(ReadError::ArrayError),
59 },
60 None => return Err(ReadError::NoAttr),
61 };
62 Ok(output)
63}
64
65fn getarrvals_aux(node: &SyntaxNode) -> Option<Vec<String>> {
66 for child in node.children() {
67 if child.kind() == rnix::SyntaxKind::NODE_WITH {
68 return getarrvals_aux(&child);
69 }
70 if child.kind() == SyntaxKind::NODE_LIST {
71 let mut out = vec![];
72 for elem in child.children() {
73 out.push(elem.to_string());
74 }
75 return Some(out);
76 }
77 }
78 None
79}
80
81pub fn getwithvalue(f: &str, query: &str) -> Result<Vec<String>, ReadError> {
82 let ast = rnix::Root::parse(f);
83 let configbase = match getcfgbase(&ast.syntax()) {
84 Some(x) => x,
85 None => {
86 return Err(ReadError::ParseError);
87 }
88 };
89 let output = match findattr(&configbase, query) {
90 Some(x) => match getwithval_aux(&x, vec![]) {
91 Some(y) => y,
92 None => return Err(ReadError::NoAttr),
93 },
94 None => return Err(ReadError::NoAttr),
95 };
96 Ok(output)
97}
98
99fn getwithval_aux(node: &SyntaxNode, mut withvals: Vec<String>) -> Option<Vec<String>> {
100 for child in node.children() {
101 if child.kind() == rnix::SyntaxKind::NODE_WITH {
102 for c in child.children() {
103 if c.kind() == rnix::SyntaxKind::NODE_IDENT {
104 let mut newvals = vec![];
105 newvals.append(withvals.as_mut());
106 newvals.push(c.to_string());
107 match getwithval_aux(&child, newvals.clone()) {
108 Some(x) => return Some(x),
109 None => return Some(newvals),
110 }
111 }
112 }
113 }
114 }
115 None
116}