• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-engine / geoengine / 3929938005

pending completion
3929938005

push

github

GitHub
Merge #713

84930 of 96741 relevant lines covered (87.79%)

79640.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.01
/operators/src/processing/expression/compiled.rs
1
use std::{
2
    fs::File,
3
    io::Write,
4
    mem::ManuallyDrop,
5
    path::{Path, PathBuf},
6
    process::Command,
7
};
8

9
use libloading::{Library, Symbol};
10
use tempfile::TempDir;
11

12
use super::{codegen::ExpressionAst, error::ExpressionError};
13

14
type Result<T, E = ExpressionError> = std::result::Result<T, E>;
15

16
/// Compiles and links an expression as a program and offers means to call it
17
pub struct LinkedExpression {
18
    library_folder: ManuallyDrop<TempDir>,
19
    library: ManuallyDrop<Library>,
20
    function_name: String,
21
}
22

23
impl LinkedExpression {
24
    pub fn new(ast: &ExpressionAst) -> Result<Self> {
10✔
25
        let library_folder = tempfile::tempdir().map_err(|error| {
10✔
26
            ExpressionError::CannotGenerateSourceCodeDirectory {
×
27
                error: error.to_string(),
×
28
            }
×
29
        })?;
10✔
30

31
        // TODO: use `rustfmt` / `formatted_code` in debug mode
32
        let input_filename =
10✔
33
            create_source_code_file(library_folder.path(), &ast.code()).map_err(|error| {
10✔
34
                ExpressionError::CannotGenerateSourceCodeFile {
×
35
                    error: error.to_string(),
×
36
                }
×
37
            })?;
10✔
38

39
        let library_filename =
10✔
40
            compile_file(library_folder.path(), &input_filename).map_err(|error| {
10✔
41
                ExpressionError::CompileError {
×
42
                    error: error.to_string(),
×
43
                }
×
44
            })?;
10✔
45

46
        let library = unsafe { Library::new(library_filename) }.map_err(|error| {
10✔
47
            ExpressionError::CompileError {
×
48
                error: error.to_string(),
×
49
            }
×
50
        })?;
10✔
51

52
        Ok(Self {
10✔
53
            library_folder: ManuallyDrop::new(library_folder),
10✔
54
            library: ManuallyDrop::new(library),
10✔
55
            function_name: ast.name().to_string(),
10✔
56
        })
10✔
57
    }
10✔
58

59
    /// Returns a function with 1 input parameters
60
    #[allow(clippy::type_complexity)]
61
    pub unsafe fn function_1<A>(&self) -> Result<Symbol<fn(A) -> Option<f64>>> {
11✔
62
        self.library
11✔
63
            .get(self.function_name.as_bytes())
11✔
64
            .map_err(|error| ExpressionError::LinkedFunctionNotFound {
11✔
65
                error: error.to_string(),
×
66
            })
11✔
67
    }
11✔
68
    /// Returns a function with 3 input parameters
69
    #[allow(clippy::type_complexity)]
70
    pub unsafe fn function_2<A, B>(&self) -> Result<Symbol<fn(A, B) -> Option<f64>>> {
26✔
71
        self.library
26✔
72
            .get(self.function_name.as_bytes())
26✔
73
            .map_err(|error| ExpressionError::LinkedFunctionNotFound {
26✔
74
                error: error.to_string(),
×
75
            })
26✔
76
    }
26✔
77

78
    /// Returns an n-ary function
79
    #[allow(clippy::type_complexity)]
80
    pub unsafe fn function_nary<F>(&self) -> Result<Symbol<F>> {
2✔
81
        self.library
2✔
82
            .get(self.function_name.as_bytes())
2✔
83
            .map_err(|error| ExpressionError::LinkedFunctionNotFound {
2✔
84
                error: error.to_string(),
×
85
            })
2✔
86
    }
2✔
87
}
88

89
impl Drop for LinkedExpression {
90
    fn drop(&mut self) {
10✔
91
        // first unlink program…
10✔
92
        unsafe { ManuallyDrop::drop(&mut self.library) };
10✔
93

10✔
94
        // …then delete files
10✔
95
        unsafe { ManuallyDrop::drop(&mut self.library_folder) };
10✔
96
    }
10✔
97
}
98

99
fn create_source_code_file(
10✔
100
    library_folder: &Path,
10✔
101
    source_code: &str,
10✔
102
) -> Result<PathBuf, std::io::Error> {
10✔
103
    let input_filename = library_folder.join("expression.rs");
10✔
104

105
    let mut file = File::create(&input_filename)?;
10✔
106
    file.write_all(source_code.as_bytes())?;
10✔
107

108
    Ok(input_filename)
10✔
109
}
10✔
110

111
fn compile_file(library_folder: &Path, input_filename: &Path) -> Result<PathBuf, std::io::Error> {
10✔
112
    let output_filename = library_folder.join("libexpression.so");
10✔
113

10✔
114
    Command::new("rustc")
10✔
115
        .args(["--crate-type", "cdylib"])
10✔
116
        .args(["-C", "opt-level=3"])
10✔
117
        .args(["-A", "warnings"]) // TODO: show warnings in debug mode
10✔
118
        .arg("-o")
10✔
119
        .arg(&output_filename)
10✔
120
        .arg(input_filename)
10✔
121
        .status()?;
10✔
122

123
    Ok(output_filename)
10✔
124
}
10✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc