// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::bss_cache::{Bss, BssId},
    async_trait::async_trait,
    fidl::{Error as FidlError, Socket as FidlSocket},
    fidl_fuchsia_location_position::{Position, PositionExtras},
    fidl_fuchsia_mem::Buffer as MemBuffer,
    fidl_fuchsia_net_http::{
        Body as HttpBody, LoaderProxyInterface, Request as HttpRequest, Response as HttpResponse,
    },
    fuchsia_async::futures::io::AsyncReadExt,
    fuchsia_async::futures::Future,
    fuchsia_zircon as zx,
    itertools::Itertools,
    serde_json::{json, map::Map as JsonMap, value::Value as JsonValue},
    static_assertions::assert_eq_size_val,
    std::{borrow::Borrow, convert::TryFrom},
};

// Geographic constants.
const LATITUDE_RANGE: std::ops::RangeInclusive<f64> = -90.0..=90.0;
const LONGITUDE_RANGE: std::ops::RangeInclusive<f64> = -180.0..=180.0;

// Google Maps constants.
const SERVICE_URL: &'static str = "https://www.googleapis.com/geolocation/v1/geolocate";
const MAC_ADDR_KEY: &'static str = "macAddress";
const AP_LIST_KEY: &'static str = "wifiAccessPoints";
const RSSI_KEY: &'static str = "signalStrength";
const LOCATION_KEY: &'static str = "location";
const LATITUDE_KEY: &'static str = "lat";
const LONGITUDE_KEY: &'static str = "lng";
const ACCURACY_KEY: &'static str = "accuracy";

// HTTP constants.
const HTTP_METHOD_POST: &'static str = "POST";

#[async_trait(?Send)]
pub trait BssResolver {
    /// Resolves WLAN BSS (base-station) meta-data to a `Position`.
    async fn resolve<'a, I, T, U>(&self, bsses: I) -> Result<Position, ResolverError>
    where
        I: IntoIterator,
        I::Item: Borrow<(T, U)>,
        T: Borrow<BssId>,
        U: Borrow<Bss>;
}

/// A service for resolving WLAN BSS (base-station) meta-data to `Position`s.
pub struct RealBssResolver<L: LoaderProxyInterface> {
    http_loader: L,
    api_key: String,
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ResolverError {
    NoBsses,
    Internal,
    Lookup,
}

impl<L: LoaderProxyInterface> RealBssResolver<L> {
    pub fn new(http_loader: L, api_key: impl Into<String>) -> Self {
        Self { http_loader, api_key: api_key.into() }
    }
}

#[async_trait(?Send)]
impl<L: LoaderProxyInterface> BssResolver for RealBssResolver<L> {
    async fn resolve<'a, I, T, U>(&self, bsses: I) -> Result<Position, ResolverError>
    where
        I: IntoIterator,
        I::Item: Borrow<(T, U)>,
        T: Borrow<BssId>,
        U: Borrow<Bss>,
    {
        let mut bsses = bsses.into_iter().peekable();
        if bsses.peek().is_none() {
            return Err(ResolverError::NoBsses);
        }
        parse_response(send_query(bsses, &self.api_key, &self.http_loader)?.await).await
    }
}

fn send_query<'a, I, T, U>(
    bsses: I,
    api_key: impl AsRef<str>,
    http_loader: &impl LoaderProxyInterface,
) -> Result<impl Future<Output = Result<HttpResponse, FidlError>>, ResolverError>
where
    I: Iterator,
    I::Item: Borrow<(T, U)>,
    T: Borrow<BssId>,
    U: Borrow<Bss>,
{
    let api_key = api_key.as_ref();
    let request_body = serialize_bsses(bsses);
    let request_size = {
        let body_size = request_body.len();
        assert_eq_size_val!(body_size, 0u64);
        u64::try_from(body_size).expect("failed to convert usize to u64")
    };
    let request_vmo = zx::Vmo::create(request_size).map_err(|_| ResolverError::Internal)?;
    let _ = request_vmo.write(&request_body.as_bytes(), 0).map_err(|_| ResolverError::Internal)?;
    Ok(http_loader.fetch(HttpRequest {
        method: Some(HTTP_METHOD_POST.to_owned()),
        url: Some(format!("{}?key={}", SERVICE_URL, api_key)),
        headers: None,
        body: Some(HttpBody::Buffer(MemBuffer { vmo: request_vmo, size: request_size })),
        deadline: None,
        ..HttpRequest::EMPTY
    }))
}

async fn parse_response(
    response: Result<HttpResponse, FidlError>,
) -> Result<Position, ResolverError> {
    let response: HttpResponse = response.map_err(|_fidl_error| ResolverError::Internal)?;
    let response: FidlSocket = response.body.ok_or(ResolverError::Lookup)?;
    let response: String = read_socket(response).await.ok_or(ResolverError::Lookup)?;
    json_to_position(serde_json::from_str(&response).map_err(|_| ResolverError::Lookup)?)
}

fn serialize_bsses<'a, I, T, U>(bsses: I) -> String
where
    I: Iterator,
    I::Item: Borrow<(T, U)>,
    T: Borrow<BssId>,
    U: Borrow<Bss>,
{
    let bsses = bsses
        .map(|item| bss_to_json(item.borrow().0.borrow(), item.borrow().1.borrow()))
        .collect::<Vec<_>>();
    json!({ AP_LIST_KEY: bsses }).to_string()
}

fn bss_to_json(bss_id: impl Borrow<BssId>, bss: impl Borrow<Bss>) -> JsonValue {
    let mut json = JsonMap::new();
    json.insert(
        MAC_ADDR_KEY.to_owned(),
        json!(bss_id.borrow().iter().map(|bss_byte| format!("{:02x}", bss_byte)).join(":")),
    );
    if let Some(rssi) = bss.borrow().rssi {
        json.insert(RSSI_KEY.to_owned(), json!(rssi));
    };
    JsonValue::from(json)
}

async fn read_socket(socket: zx::Socket) -> Option<String> {
    let mut buf = Vec::new();
    match fuchsia_async::Socket::from_socket(socket).ok() {
        Some(mut socket) => match socket.read_to_end(&mut buf).await {
            Ok(_num_bytes_read) => String::from_utf8(buf).ok(),
            Err(_) => None,
        },
        None => None,
    }
}

fn json_to_position(response: JsonValue) -> Result<Position, ResolverError> {
    let latitude = response[LOCATION_KEY][LATITUDE_KEY].as_f64().ok_or(ResolverError::Lookup)?;
    if !LATITUDE_RANGE.contains(&latitude) {
        return Err(ResolverError::Lookup);
    }

    let longitude = response[LOCATION_KEY][LONGITUDE_KEY].as_f64().ok_or(ResolverError::Lookup)?;
    if !LONGITUDE_RANGE.contains(&longitude) {
        return Err(ResolverError::Lookup);
    }

    let extras = match response[ACCURACY_KEY].as_f64() {
        Some(accuracy) => PositionExtras {
            accuracy_meters: Some(accuracy),
            altitude_meters: None,
            ..PositionExtras::EMPTY
        },
        None => {
            PositionExtras { accuracy_meters: None, altitude_meters: None, ..PositionExtras::EMPTY }
        }
    };

    Ok(Position { latitude, longitude, extras })
}

#[cfg(test)]
mod tests {
    mod request_generation {
        use {
            super::super::{test_doubles::HttpRequestValidator, *},
            fuchsia_async as fasync,
        };

        #[fasync::run_until_stalled(test)]
        async fn request_uses_post_method() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: Some(-30), frequency: Some(2412) })];
            let mut request_method = None;
            let http_loader = HttpRequestValidator::new(|request| {
                request_method = Some(request.method.expect("request had no method"));
            });
            let _ = RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await;
            assert_eq!(request_method.expect("request was never issued"), "POST".to_owned());
        }

        #[fasync::run_until_stalled(test)]
        async fn request_url_is_correct() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: Some(-30), frequency: Some(2412) })];
            let mut request_url = None;
            let http_loader = HttpRequestValidator::new(|request| {
                request_url = Some(request.url.expect("request had no url"));
            });
            let _ = RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await;
            assert_eq!(
                request_url.expect("request was never issued"),
                "https://www.googleapis.com/geolocation/v1/geolocate?key=fake_key".to_owned()
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn request_body_contains_all_bsses() {
            let bsses = vec![
                ([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None }),
                ([1, 1, 1, 1, 1, 1], Bss { rssi: None, frequency: None }),
            ];
            let mut request_body = None;
            let http_loader = HttpRequestValidator::new(|request| {
                request_body = Some(request.body.expect("request had no body"));
            });
            let _ = RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await;
            assert_eq!(
                strip_whitespace(read_request_body(
                    request_body.expect("request was never issued")
                )),
                strip_whitespace(
                    r#"{
                    "wifiAccessPoints":[
                        {"macAddress":"00:00:00:00:00:00"},
                        {"macAddress":"01:01:01:01:01:01"}
                    ]
                }"#
                )
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn request_body_includes_rssi() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: Some(-30), frequency: None })];
            let mut request_body = None;
            let http_loader = HttpRequestValidator::new(|request| {
                request_body = Some(request.body.expect("request had no body"));
            });
            let _ = RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await;
            assert_eq!(
                strip_whitespace(read_request_body(
                    request_body.expect("request was never issued")
                )),
                strip_whitespace(
                    r#"{
                    "wifiAccessPoints":[
                        {"macAddress":"00:00:00:00:00:00",
                         "signalStrength": -30}
                    ]
                }"#
                )
            )
        }

        #[fasync::run_until_stalled(test)]
        async fn skips_api_query_when_bsses_is_empty() {
            let http_loader =
                HttpRequestValidator::new(|_request| panic!("should not issue API query"));
            let _ = RealBssResolver::new(http_loader, "fake_key")
                .resolve(std::iter::empty::<(BssId, Bss)>())
                .await;
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_no_bsses_error_when_bsses_is_empty() {
            let http_loader = HttpRequestValidator::new(|_| ());
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key")
                    .resolve(std::iter::empty::<(BssId, Bss)>())
                    .await,
                Err(ResolverError::NoBsses)
            );
        }

        fn read_request_body(body: HttpBody) -> String {
            match body {
                HttpBody::Buffer(shared_buf) => {
                    let mut local_buf = vec![
                        0_u8;
                        usize::try_from(shared_buf.size).expect(
                            "internal error: failed to convert u64 to usize"
                        )
                    ];
                    shared_buf
                        .vmo
                        .read(&mut local_buf, 0)
                        .expect("internal error: failed to read from VMO");
                    String::from_utf8(local_buf)
                        .expect("internal error: failed to convert buffer to UTF-8")
                }
                HttpBody::Stream(_) => panic!("internal error: stream bodies not supported"),
            }
        }

        fn strip_whitespace<S: AsRef<str>>(input: S) -> String {
            input.as_ref().replace("\n", "").replace(" ", "")
        }
    }

    mod response_error_handling {
        use {
            super::super::{
                test_doubles::{HttpByteResponder, HttpFidlResponder},
                *,
            },
            fuchsia_async as fasync,
        };

        #[fasync::run_until_stalled(test)]
        async fn returns_internal_error_on_fidl_error() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpFidlResponder::new(|| Err(FidlError::InvalidHeader));
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Internal)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_response_has_no_body() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpFidlResponder::new(|| {
                Ok(HttpResponse {
                    error: None,
                    body: None,
                    final_url: None,
                    status_code: None,
                    status_line: None,
                    headers: None,
                    redirect: None,
                    ..HttpResponse::EMPTY
                })
            });
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_unreadable() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpFidlResponder::new(|| {
                Ok(HttpResponse {
                    error: None,
                    body: Some(zx::Socket::from(zx::Handle::invalid())),
                    final_url: None,
                    status_code: None,
                    status_line: None,
                    headers: None,
                    redirect: None,
                    ..HttpResponse::EMPTY
                })
            });
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_not_valid_json() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(b"hello world".to_vec());
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_not_a_dictionary() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(b"42".to_vec());
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_missing_location() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(b"{}".to_vec());
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_missing_latitude() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                          "lng": -0.1
                        },
                        "accuracy": 1200.4
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_body_is_missing_longitude() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 51.0,
                        },
                        "accuracy": 1200.4
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_latitude_is_too_high() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 90.1,
                            "lng": 0.0
                        }
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_latitude_is_too_low() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": -90.1,
                            "lng": 0.0
                        }
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_longitude_is_too_high() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 0.0,
                            "lng": 180.1
                        }
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_lookup_error_when_longitude_is_too_low() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 0.0,
                            "lng": -180.1
                        }
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Err(ResolverError::Lookup)
            );
        }
    }

    mod response_success_reporting {
        use {
            super::super::{test_doubles::HttpByteResponder, *},
            fuchsia_async as fasync,
            matches::assert_matches,
        };

        #[fasync::run_until_stalled(test)]
        async fn returns_success_when_all_fields_are_present() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 51.0,
                            "lng": -0.1
                        },
                        "accuracy": 1200.4
                }"#
                .to_vec(),
            );
            assert_matches!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Ok(_)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn returns_success_when_all_fields_except_accuracy_are_present() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 51.0,
                            "lng": -0.1
                       }
                }"#
                .to_vec(),
            );
            assert_matches!(
                RealBssResolver::new(http_loader, "fake_key").resolve(bsses).await,
                Ok(_)
            );
        }
    }

    mod response_success_contents {
        use {
            super::super::{test_doubles::HttpByteResponder, *},
            fuchsia_async as fasync,
            matches::assert_matches,
        };

        #[fasync::run_until_stalled(test)]
        async fn provides_precise_latitude() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 89.0,
                            "lng": 0
                       }
                }"#
                .to_vec(),
            );
            assert_matches!(
                RealBssResolver::new(http_loader, "fake_key")
                    .resolve(bsses)
                    .await.expect("position is none").latitude,
                // One degree of latitude is approximately 111 kilometers. By limiting rounding
                // error to 1/10,000,000 of a degree, we limit rounding error to
                // 111/10000 = 0.011 meters, or  1.1 cm.
                latitude if (88.999_999_9..89.000_000_1).contains(&latitude)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn provides_precise_longitude() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 0,
                            "lng": 179.0
                       }
                }"#
                .to_vec(),
            );
            assert_matches!(
                RealBssResolver::new(http_loader, "fake_key")
                    .resolve(bsses)
                    .await.expect("no position").longitude,
                // At the equator, one degree of longitude is approximately 111 kilometers.
                // By limiting rounding error to 1/10,000,000 of a degree, we limit rounding error
                // to 111/10000 = 0.011 meters, or  1.1 cm.
                longitude if (178.999_999_9..179.099_999_9).contains(&longitude)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn provides_precise_accuracy_when_present() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 51.0,
                            "lng": -0.1
                        },
                        "accuracy": 1200.4
                }"#
                .to_vec(),
            );
            assert_matches!(
                RealBssResolver::new(http_loader, "fake_key")
                    .resolve(bsses)
                    .await.expect("no position").extras.accuracy_meters.expect("accuracy is none"),
                accuracy if (1200.39..1200.41).contains(&accuracy)
            );
        }

        #[fasync::run_until_stalled(test)]
        async fn does_not_fabricate_accuracy() {
            let bsses = vec![([0, 0, 0, 0, 0, 0], Bss { rssi: None, frequency: None })];
            let http_loader = HttpByteResponder::new(
                br#"{
                        "location": {
                            "lat": 51.0,
                            "lng": -0.1
                        }
                }"#
                .to_vec(),
            );
            assert_eq!(
                RealBssResolver::new(http_loader, "fake_key")
                    .resolve(bsses)
                    .await
                    .expect("no position")
                    .extras
                    .accuracy_meters,
                None
            );
        }
    }
}

#[cfg(test)]
mod test_doubles {
    use {
        super::*,
        fidl::endpoints::ClientEnd,
        fidl_fuchsia_net_http::LoaderClientMarker,
        fuchsia_async::futures::future::{ready, Ready},
        std::sync::RwLock,
    };

    const HTTP_OK: u32 = 200;

    type FetchResponse = Result<HttpResponse, FidlError>;

    // Test double that
    // 1) invokes `validate` to run test assertions, and
    // 2) returns HTTP_OK, assuming `validate` did not abort
    pub(super) struct HttpRequestValidator<F>
    where
        F: FnMut(HttpRequest) + Send + Sync,
    {
        // RwLock is needed because
        // a) we need interior mutability for F to be FnMut, and
        // b) we need to implement Send and Sync.
        validate: RwLock<F>,
    }

    // Test double that invokes a function which yields `FetchResponse`,
    // and returns that as a FIDL response. Useful for testing error
    // handling.
    pub(super) struct HttpFidlResponder<F>
    where
        F: Fn() -> FetchResponse + Send + Sync,
    {
        fetch: F,
    }

    // Test double that invokes a function which yields a `Vec<u8>`,
    // and returns the Vec as the HTTP response. Useful for testing
    // response parsing.
    pub(super) struct HttpByteResponder {
        response: Vec<u8>,
    }

    impl<F> HttpRequestValidator<F>
    where
        F: FnMut(HttpRequest) + Send + Sync,
    {
        pub(super) fn new(validate: F) -> Self {
            Self { validate: RwLock::new(validate) }
        }
    }

    impl<F> LoaderProxyInterface for HttpRequestValidator<F>
    where
        F: FnMut(HttpRequest) + Send + Sync,
    {
        type FetchResponseFut = Ready<Result<HttpResponse, FidlError>>;

        fn fetch(&self, request: HttpRequest) -> Self::FetchResponseFut {
            // Note: the `&mut *` here is due to https://github.com/rust-lang/rust/issues/65489
            let validate = &mut *self.validate.write().expect("internal error");
            let final_url = request.url.clone();
            validate(request);
            ready(Ok(HttpResponse {
                error: None,
                body: None,
                final_url,
                status_code: Some(HTTP_OK),
                status_line: None,
                headers: None,
                redirect: None,
                ..HttpResponse::EMPTY
            }))
        }

        fn start(
            &self,
            _request: HttpRequest,
            _client: ClientEnd<LoaderClientMarker>,
        ) -> Result<(), FidlError> {
            panic!("internal error: this fake does not implement `start()`");
        }
    }

    impl<F> HttpFidlResponder<F>
    where
        F: Fn() -> FetchResponse + Send + Sync,
    {
        pub(super) fn new(fetch: F) -> Self {
            Self { fetch }
        }
    }

    impl<F> LoaderProxyInterface for HttpFidlResponder<F>
    where
        F: Fn() -> FetchResponse + Send + Sync,
    {
        type FetchResponseFut = Ready<FetchResponse>;

        fn fetch(&self, _request: HttpRequest) -> Self::FetchResponseFut {
            ready((self.fetch)())
        }

        fn start(
            &self,
            _request: HttpRequest,
            _client: ClientEnd<LoaderClientMarker>,
        ) -> Result<(), FidlError> {
            panic!("internal error: this stub does not implement `start()`");
        }
    }

    impl HttpByteResponder {
        pub(super) fn new(response: Vec<u8>) -> Self {
            Self { response }
        }
    }

    impl LoaderProxyInterface for HttpByteResponder {
        type FetchResponseFut = Ready<FetchResponse>;

        fn fetch(&self, _request: HttpRequest) -> Self::FetchResponseFut {
            let (local_socket, remote_socket) =
                zx::Socket::create(zx::SocketOpts::STREAM).expect("internal error");
            local_socket.write(&self.response).expect("internal error");
            ready(Ok(HttpResponse {
                error: None,
                body: Some(remote_socket),
                final_url: None,
                status_code: Some(HTTP_OK),
                status_line: None,
                headers: None,
                redirect: None,
                ..HttpResponse::EMPTY
            }))
        }

        fn start(
            &self,
            _request: HttpRequest,
            _client: ClientEnd<LoaderClientMarker>,
        ) -> Result<(), FidlError> {
            panic!("internal error: this stub does not implement `start()`");
        }
    }
}
