1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//! # Azure Functions for Rust
//!
//! The Azure Functions for Rust crate supports creating Azure Functions with Rust.
//!
//! The following Azure Functions trigger bindings are supported:
//!
//! * [Blob trigger](bindings/struct.BlobTrigger.html)
//! * [Cosmos DB trigger](bindings/struct.CosmosDbTrigger.html)
//! * [Durable Activity trigger](bindings/struct.DurableOrchestrationContext.html)
//! * [Durable Orchestration trigger](bindings/struct.DurableOrchestrationContext.html)
//! * [Event Grid trigger](bindings/struct.EventGridEvent.html)
//! * [Event Hub trigger](bindings/struct.EventHubTrigger.html)
//! * [Generic trigger](bindings/struct.GenericTrigger.html)
//! * [HTTP trigger](bindings/struct.HttpRequest.html)
//! * [Service Bus trigger](bindings/struct.ServiceBusTrigger.html)
//! * [Queue trigger](bindings/struct.QueueTrigger.html)
//! * [Timer trigger](bindings/struct.TimerInfo.html)
//!
//! The following Azure Functions input bindings are supported:
//!
//! * [Blob input](bindings/struct.Blob.html)
//! * [Cosmos DB input](bindings/struct.CosmosDbDocument.html)
//! * [Durable orchestration client input](bindings/struct.DurableOrchestrationClient.html)
//! * [Generic input](bindings/struct.GenericInput.html)
//! * [SignalR connection info input](bindings/struct.SignalRConnectionInfo.html)
//! * [Table input](bindings/struct.Table.html)
//!
//! The following Azure Functions output bindings are supported:
//!
//! * [Blob output](bindings/struct.Blob.html)
//! * [Cosmos DB output](bindings/struct.CosmosDbDocument.html)
//! * [Event Hub output](bindings/struct.EventHubMessage.html)
//! * [Generic output](bindings/struct.GenericOutput.html)
//! * [HTTP output](bindings/struct.HttpResponse.html)
//! * [Queue output](bindings/struct.QueueMessage.html)
//! * [SendGrid email message output](bindings/struct.SendGridMessage.html)
//! * [Service Bus output](bindings/struct.ServiceBusMessage.html)
//! * [SignalR group action output](bindings/struct.SignalRGroupAction.html)
//! * [SignalR message output](bindings/struct.SignalRMessage.html)
//! * [Table output](bindings/struct.Table.html)
//! * [Twilio SMS message output](bindings/struct.TwilioSmsMessage.html)
//!
//! Eventually more bindings will be implemented, including custom binding data.
//!
//! # Example
//!
//! Start by installing the Azure Functions for Rust SDK:
//!
//! ```bash
//! $ cargo install azure-functions-sdk
//! ```
//!
//! Create a new Azure Functions for Rust application:
//!
//! ```bash
//! $ cargo func new-app hello && cd hello
//! ```
//!
//! Create a HTTP-triggered function:
//!
//! ```bash
//! $ cargo func new http -n hello
//! ```
//!
//! This generates `src/functions/hello.rs` with the following contents:
//!
//! ```rust,ignore
//! use azure_functions::{
//!     bindings::{HttpRequest, HttpResponse},
//!     func,
//! };
//!
//! #[func]
//! pub fn hello(req: HttpRequest) -> HttpResponse {
//!     "Hello from Rust!".into()
//! }
//! ```
//!
//! Azure Functions are implemented by applying a `#[func]` attribute to a Rust function.
//!
//! Run the application with `cargo func run`:
//!
//! ```bash
//! $ cargo func run
//! ```
//!
//! The above Azure Function can be invoked with `http://localhost:8080/api/hello`.
//!
//! The expected response would be `Hello from Rust!`.
#![deny(unused_extern_crates)]
#![deny(missing_docs)]
#![cfg_attr(test, recursion_limit = "128")]

#[doc(no_inline)]
pub use azure_functions_codegen::export;
#[doc(no_inline)]
pub use azure_functions_codegen::func;

#[doc(hidden)]
pub use azure_functions_shared::codegen;

mod backtrace;
mod commands;
mod logger;
mod registry;
mod util;
mod worker;

pub mod bindings;
pub mod blob;
pub mod context;
pub mod durable;
pub mod event_hub;
pub mod generic;
pub mod http;
pub mod send_grid;
pub mod signalr;
pub mod timer;
#[doc(no_inline)]
pub use azure_functions_shared::rpc;

use crate::commands::{Init, Run, SyncExtensions};
use crate::registry::Registry;
use clap::{App, AppSettings};

#[doc(hidden)]
pub trait IntoVec<T> {
    fn into_vec(self) -> Vec<T>;
}

#[doc(hidden)]
pub trait FromVec<T> {
    fn from_vec(vec: Vec<T>) -> Self;
}

/// The main entry point for the Azure Functions for Rust worker.
///
/// This entry point does not use any additional Azure Functions binding extensions.
///
/// # Examples
///
/// ```rust,ignore
/// mod example;
///
/// azure_functions::export! {
///     example::function,
/// }
///
/// fn main() {
///     azure_functions::worker_main(::std::env::args(), EXPORTS);
/// }
/// ```
pub fn worker_main(args: impl Iterator<Item = String>, functions: &[&'static codegen::Function]) {
    worker_main_with_extensions(args, functions, &[])
}

/// The main entry point for the Azure Functions for Rust worker.
///
/// This entry point uses additional Azure Function binding extensions.
///
/// # Examples
///
/// ```rust,ignore
/// fn main() {
///     azure_functions::worker_main_with_extensions(
///         ::std::env::args(),
///         functions::EXPORTS,
///         &[("Microsoft.Azure.WebJobs.Extensions.Kafka", "1.0.0-alpha")]
///     );
/// }
/// ```
pub fn worker_main_with_extensions(
    args: impl Iterator<Item = String>,
    functions: &[&'static codegen::Function],
    extensions: &[(&str, &str)],
) {
    let registry = Registry::new(functions);

    let app = App::new("Azure Functions for Rust worker")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Implements the Azure Functions for Rust worker.")
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::VersionlessSubcommands)
        .subcommand(Init::create_subcommand())
        .subcommand(SyncExtensions::create_subcommand())
        .subcommand(Run::create_subcommand());

    if let Err(e) = match app.get_matches_from(args).subcommand() {
        ("init", Some(args)) => Init::from(args).execute(registry, extensions),
        ("sync-extensions", Some(args)) => SyncExtensions::from(args).execute(registry, extensions),
        ("run", Some(args)) => Run::from(args).execute(registry),
        _ => panic!("expected a subcommand."),
    } {
        eprintln!("error: {}", e);
        std::process::exit(1);
    }
}