Skip to main content

ieql/output/
output.rs

1//! This file provides functionality related to outputs.
2
3use common::pattern::PatternMatch;
4use input::document::CompiledDocument;
5use query::query::CompiledQuery;
6use query::response::{ResponseItem, ResponseKind};
7
8/// `Output` represents a 'match' of a Query. It is the primary
9/// product of an IEQL scan, and contains many variable (and configurable)
10/// pieces of data and metadata.
11/// 
12/// _Note: `response` and `output` are synonymous in the context of this
13/// documentation._
14/// 
15/// Outputs have two kinds: `Full` and `Partial`. Full outputs are for
16/// matches which exist on their own—for example, a match of someone's
17/// name online. Partial outputs, however, are meant to be MapReduced.
18/// For example, if a linguist wanted to count the number of times a certain
19/// word appears online, they would configure their query to produce a `Partial`
20/// response, which they would then MapReduce.
21/// 
22/// There is not currently full support for partial IEQL outputs.
23#[derive(Serialize, Deserialize, Debug, PartialEq)]
24pub struct Output {
25    /// Contains the data relevant for the user; for example, excerpts of the match.
26    pub items: Vec<OutputItem>,
27    /// Represents the _kind_ of the output (`Full` or `Partial`).
28    pub kind: OutputKind,
29    /// This is an optional value for identifying the output, and can vary
30    /// based on your implementation. In most cases, when present, this 
31    /// is some form of UUID.
32    pub id: Option<String>,
33    /// This is the ID of the query that created the output. Note that this
34    /// will only be present when the query that created the output itself
35    /// has an id.
36    pub query_id: Option<String>,
37}
38
39/// This enum specifies the output type of the query. For more information
40/// about each type of query, please see the specification.
41/// 
42/// **There is currently not full support for partial queries.**
43#[derive(Serialize, Deserialize, Debug, PartialEq)]
44pub enum OutputKind {
45    Full,
46    Partial,
47}
48
49/// This enum represents a possible output item. `OutputItem`s are typically
50/// user-meaningful, and are not machine readable. The items included in the
51/// output are dependent on the `response` configuration of the query.
52/// 
53/// Much of this information is simply copied from the metadata of the document
54/// that produced it.
55#[derive(Serialize, Deserialize, Debug, PartialEq)]
56pub enum OutputItem {
57    /// Represents the URL of the document that matched the query, if present.
58    /// There is _no guarantee_ that this will be a valid url; if the mechanism
59    /// by which documents are loaded provides a faulty or invalid URL (such as
60    /// a local filepath, as the command line interface does when loading documents),
61    /// this URL will be unchanged.
62    Url(Option<String>),
63    /// Represents a valid IETF MIME type, as per RFC 2045.
64    Mime(Option<String>),
65    /// Represents the domain (or hostname) of the `Url`. When the URL is not present, neither
66    /// will the domain be.
67    Domain(Option<String>),
68    /// Contains any number of `PatternMatch`es—in other words, excerpts.
69    Excerpt(Vec<PatternMatch>),
70    /// Contains the full content of the matched page
71    FullContent(Option<String>)
72}
73
74/// Represents a batch (collection) of outputs. This function tends to be
75/// helpful for multiprocessing, though it is somewhat infrequently used.
76#[derive(Serialize, Deserialize, Debug, PartialEq)]
77pub struct OutputBatch {
78    /// Contains the outputs.
79    pub outputs: Vec<Output>,
80}
81
82impl From<Vec<Output>> for OutputBatch {
83    fn from(outputs: Vec<Output>) -> OutputBatch {
84        OutputBatch { outputs: outputs }
85    }
86}
87
88fn string_clone_helper(to_clone: &Option<String>) -> Option<String> {
89    match to_clone {
90        Some(value) => Some(value.clone()),
91        None => None,
92    }
93}
94
95impl Output {
96    /// Create a new output from the given data. Please note that this
97    /// operation is **expensive**!
98    /// 
99    /// # Arguments
100    /// * `document`: the compiled document that the query matched
101    /// * `query`: the compiled query that matched the document
102    /// * `matches`: the `PatternMatch`es produced by the queries' triggers
103    /// * `id`: the optional ID of the desired output
104    pub fn new(
105        document: &CompiledDocument,
106        query: &CompiledQuery,
107        matches: Vec<PatternMatch>,
108        id: Option<String>,
109    ) -> Output {
110        // warning: expensive!
111        let kind = match query.response.kind {
112            ResponseKind::Full => OutputKind::Full,
113            ResponseKind::Partial => OutputKind::Partial,
114        };
115        let query_id = string_clone_helper(&query.id);
116        let mut items: Vec<OutputItem> = Vec::new();
117        for item in &query.response.include {
118            match item {
119                ResponseItem::Domain => items.push(OutputItem::Domain((&document.domain).clone())),
120                ResponseItem::Mime => {
121                    items.push(OutputItem::Mime(string_clone_helper(&document.mime)))
122                }
123                ResponseItem::Url => {
124                    items.push(OutputItem::Url(string_clone_helper(&document.url)))
125                }
126                ResponseItem::Excerpt => items.push(OutputItem::Excerpt(matches.clone())),
127                ResponseItem::FullContent => items.push(OutputItem::FullContent(Some((&document.raw).clone())))
128            }
129        }
130        Output {
131            items: items,
132            kind: kind,
133            id: id,
134            query_id: query_id,
135        }
136    }
137}
138
139impl OutputBatch {
140    /// Merges the output batch with the other output
141    /// batch. This function _consumes_ the other output
142    /// batch, but involves no memory duplication.
143    pub fn merge_with(&mut self, other: OutputBatch) {
144        self.outputs.extend(other.outputs);
145    }
146
147    /// Create a new empty output batch.
148    pub fn new() -> OutputBatch {
149        OutputBatch::from(vec![])
150    }
151}
152
153impl std::fmt::Display for Output {
154    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
155        let id = match &self.id {
156            Some(value) => format!("[{}]", value),
157            None => String::from(""),
158        };
159        let kind = match self.kind {
160            OutputKind::Full => "full response",
161            OutputKind::Partial => "partial response",
162        };
163        let query_id = match &self.query_id {
164            Some(value) => format!(" from `{}`", value),
165            None => String::from(""),
166        };
167        let mut items: Vec<String> = Vec::new();
168        for item in &self.items {
169            items.push(format!("{:?}", item));
170        }
171        write!(f, "{} {}{}: {:?}", id, kind, query_id, items)
172    }}