-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
2,646 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,55 @@ | ||
varnish::boilerplate!(); | ||
|
||
use std::fs::read_to_string; | ||
|
||
use varnish::vcl::ctx::Ctx; | ||
|
||
varnish::vtc!(test01); | ||
|
||
// no error, just return 0 if anything goes wrong | ||
pub fn cannot_fail(_: &Ctx, fp: &str) -> i64 { | ||
// try to read the path at fp into a string, but return if there was an error | ||
let Ok(content) = read_to_string(fp) else { | ||
return 0; | ||
}; | ||
|
||
// try to convert the string into an i64, if parsing fails, force 0 | ||
// no need to return as the last expression is automatically returned | ||
content.parse::<i64>().unwrap_or(0) | ||
} | ||
|
||
// we call ctx.fail() ourselves, but we still need to return an i64 (which will | ||
// be discarded), so we just convert the 0_u8 returned into an i64 (.into() is | ||
// smart enough to infer the type) | ||
pub fn manual_fail(ctx: &mut Ctx, fp: &str) -> i64 { | ||
// try to read the path at fp into a string, but return if there was an error | ||
let Ok(content) = read_to_string(fp) else { | ||
return ctx | ||
.fail("manual_fail: couldn't read file into string") | ||
.into(); | ||
}; | ||
|
||
// try to convert the string into an i64 | ||
// no need to return as the last expression is automatically returned | ||
content | ||
.parse::<i64>() | ||
.unwrap_or_else(|_| ctx.fail("manual_fail: conversion failed").into()) | ||
/// This is a simple example of how to handle errors in a Varnish VMOD. | ||
#[varnish::vmod] | ||
mod error { | ||
use std::fs::read_to_string; | ||
|
||
use varnish::vcl::ctx::Ctx; | ||
|
||
/// This function never fails, returning 0 if anything goes wrong | ||
pub fn cannot_fail(path: &str) -> i64 { | ||
// try to read the path at fp into a string, but return if there was an error | ||
let Ok(content) = read_to_string(path) else { | ||
return 0; | ||
}; | ||
|
||
// try to convert the string into an i64, if parsing fails, force 0 | ||
// no need to return as the last expression is automatically returned | ||
content.parse::<i64>().unwrap_or(0) | ||
} | ||
|
||
// we call ctx.fail() ourselves, but we still need to return an i64 (which will | ||
// be discarded), so we just convert the 0_u8 returned into an i64 (.into() is | ||
// smart enough to infer the type) | ||
pub fn manual_fail(ctx: &mut Ctx, fp: &str) -> i64 { | ||
// try to read the path at fp into a string, but return if there was an error | ||
let Ok(content) = read_to_string(fp) else { | ||
return ctx | ||
.fail("manual_fail: couldn't read file into string") | ||
.into(); | ||
}; | ||
|
||
// try to convert the string into an i64 | ||
// no need to return as the last expression is automatically returned | ||
content | ||
.parse::<i64>() | ||
.unwrap_or_else(|_| ctx.fail("manual_fail: conversion failed").into()) | ||
} | ||
|
||
// more idiomatic, we return a Result, and the generated boilerplate will be in charge of | ||
// calling `ctx.fail() and return a dummy value | ||
pub fn result_fail(fp: &str) -> Result<i64, String> { | ||
read_to_string(fp) // read the file | ||
.map_err(|e| format!("result_fail: {e}"))? // convert the error (if any!), into a string | ||
// the ? will automatically return in case | ||
// of an error | ||
.parse::<i64>() // convert | ||
// map the type, and we are good to | ||
// automatically return | ||
.map_err(|e| format!("result_fail: {e}")) | ||
} | ||
} | ||
|
||
// more idiomatic, we return a Result, and the generated boilerplate will be in charge of | ||
// calling `ctx.fail() and return a dummy value | ||
pub fn result_fail(_: &mut Ctx, fp: &str) -> Result<i64, String> { | ||
read_to_string(fp) // read the file | ||
.map_err(|e| format!("result_fail: {e}"))? // convert the error (if any!), into a string | ||
// the ? will automatically return in case | ||
// of an error | ||
.parse::<i64>() // convert | ||
.map_err(|e| format!("result_fail: {e}")) // map the type, and we are good to | ||
// automatically return | ||
#[cfg(test)] | ||
mod tests { | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,45 @@ | ||
// import the generated boilerplate | ||
varnish::boilerplate!(); | ||
#[varnish::vmod] | ||
mod example { | ||
// we now implement both functions from vmod.vcc, but with rust types. | ||
// Don't forget to make the function public with "pub" in front of them | ||
|
||
// even though we won't use it here, we still need to know what the context type is | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
// we now implement both functions from vmod.vcc, but with rust types. | ||
// Don't forget to make the function public with "pub" in front of them | ||
|
||
pub fn is_even(_: &Ctx, n: i64) -> bool { | ||
n % 2 == 0 | ||
} | ||
pub fn is_even(n: i64) -> bool { | ||
n % 2 == 0 | ||
} | ||
|
||
// in vmod.vcc, n was an optional INT, so here it translates into an Option<i64> | ||
pub fn captain_obvious(_: &Ctx, opt: Option<i64>) -> String { | ||
// we need to first "match" to know if a number was provided, if not, | ||
// return a default message, otherwise, build a custom one | ||
match opt { | ||
// no need to return, we are the last expression of the function! | ||
None => String::from("I was called without an argument"), | ||
// pattern matching FTW! | ||
Some(n) => format!("I was given {n} as argument"), | ||
// in vmod.vcc, n was an optional INT, so here it translates into an Option<i64> | ||
pub fn captain_obvious(opt: Option<i64>) -> String { | ||
// we need to first "match" to know if a number was provided, if not, | ||
// return a default message, otherwise, build a custom one | ||
match opt { | ||
// no need to return, we are the last expression of the function! | ||
None => String::from("I was called without an argument"), | ||
// pattern matching FTW! | ||
Some(n) => format!("I was given {n} as argument"), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use varnish::vcl::ctx::TestCtx; | ||
use super::example::*; | ||
|
||
use super::*; | ||
// test with test/test01.vtc | ||
varnish::vtc!(test01); | ||
|
||
#[test] | ||
fn obviousness() { | ||
let mut test_ctx = TestCtx::new(100); | ||
let ctx = test_ctx.ctx(); | ||
|
||
assert_eq!( | ||
"I was called without an argument", | ||
captain_obvious(&ctx, None) | ||
); | ||
assert_eq!("I was called without an argument", captain_obvious(None)); | ||
assert_eq!( | ||
"I was given 975322 as argument", | ||
captain_obvious(&ctx, Some(975_322)) | ||
captain_obvious(Some(975_322)) | ||
); | ||
} | ||
|
||
#[test] | ||
fn even_test() { | ||
// we don't use it, but we still need one | ||
let mut test_ctx = TestCtx::new(100); | ||
let ctx = test_ctx.ctx(); | ||
|
||
assert!(is_even(&ctx, 0)); | ||
assert!(is_even(&ctx, 1024)); | ||
assert!(!is_even(&ctx, 421_321)); | ||
assert!(is_even(0)); | ||
assert!(is_even(1024)); | ||
assert!(!is_even(421_321)); | ||
} | ||
|
||
// we also want to run test/test01.vtc | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,27 @@ | ||
varnish::boilerplate!(); | ||
#[varnish::vmod] | ||
mod infiniteloop { | ||
use varnish::ffi::{BUSYOBJ_MAGIC, REQ_MAGIC}; | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
use varnish::ffi::{BUSYOBJ_MAGIC, REQ_MAGIC}; | ||
use varnish::vcl::ctx::Ctx; | ||
|
||
varnish::vtc!(test01); | ||
|
||
/// # Safety | ||
/// this function is unsafe from the varnish point of view, doing away with | ||
/// important safeguards, but it's also unsafe in the rust way: it dereferences | ||
/// pointers which may lead nowhere | ||
pub unsafe fn reset(ctx: &mut Ctx) { | ||
if let Some(req) = ctx.raw.req.as_mut() { | ||
assert_eq!(req.magic, REQ_MAGIC); | ||
req.restarts = 0; | ||
} | ||
if let Some(bo) = ctx.raw.bo.as_mut() { | ||
assert_eq!(bo.magic, BUSYOBJ_MAGIC); | ||
bo.retries = 0; | ||
/// # Safety | ||
/// this function is unsafe from the varnish point of view, doing away with | ||
/// important safeguards, but it's also unsafe in the rust way: it dereferences | ||
/// pointers which may lead nowhere | ||
pub fn reset(ctx: &mut Ctx) { | ||
unsafe { | ||
if let Some(req) = ctx.raw.req.as_mut() { | ||
assert_eq!(req.magic, REQ_MAGIC); | ||
req.restarts = 0; | ||
} | ||
if let Some(bo) = ctx.raw.bo.as_mut() { | ||
assert_eq!(bo.magic, BUSYOBJ_MAGIC); | ||
bo.retries = 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,31 @@ | ||
varnish::boilerplate!(); | ||
#[varnish::vmod] | ||
mod timestamp { | ||
use std::mem; | ||
use std::time::{Duration, Instant}; | ||
|
||
use std::time::{Duration, Instant}; | ||
/// Returns the time interval since the last time this function was called in the current task's context. | ||
/// There could be only one type of per-task shared context data type in a Varnish VMOD. | ||
pub fn timestamp(#[shared_per_task] task_ctx: &mut Option<Box<Instant>>) -> Duration { | ||
// we will need this either way | ||
let now = Instant::now(); | ||
|
||
use varnish::vcl::ctx::Ctx; | ||
use varnish::vcl::vpriv::VPriv; | ||
|
||
varnish::vtc!(test01); | ||
|
||
// VPriv can wrap any (possibly custom) struct, here we only need an Instant from std::time. | ||
// Storing and getting is up to the vmod writer but this removes the worry of NULL dereferencing | ||
// and of the memory management | ||
pub fn timestamp(_: &Ctx, vp: &mut VPriv<Instant>) -> Duration { | ||
// we will need this either way | ||
let now = Instant::now(); | ||
match task_ctx { | ||
None => { | ||
// This is the first time we're running this function in the task's context | ||
*task_ctx = Some(Box::new(now)); | ||
Duration::default() | ||
} | ||
Some(task_ctx) => { | ||
// Update box content in-place to the new value, and get the old value | ||
let old_now = mem::replace(&mut **task_ctx, now); | ||
// Since Instant implements Copy, we can continue using it and subtract the old value | ||
now.duration_since(old_now) | ||
} | ||
} | ||
} | ||
} | ||
|
||
let interval = match vp.as_ref() { | ||
// if `.get()` returns None, we just store `now` and interval is 0 | ||
None => Duration::new(0, 0), | ||
// if there was a value, compute the difference with now | ||
Some(old_now) => now.duration_since(*old_now), | ||
}; | ||
// store the current time and return `interval` | ||
vp.store(now); | ||
interval | ||
#[cfg(test)] | ||
mod tests { | ||
varnish::vtc!(test01); | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.