<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;

#[test]
fn eval_void() {
    use std::rc::Rc;
    use std::cell::Cell;
    gj::EventLoop::top_level(|wait_scope| {
        let done = Rc::new(Cell::new(false));
        let done1 = done.clone();
        let promise : gj::Promise<(), Box<::std::error::Error>> =
            gj::Promise::fulfilled(()).map(move |()| {
                done1.clone().set(true);
                Ok(())
            });
        assert_eq!(done.get(), false);
        promise.wait(wait_scope).unwrap();
        assert_eq!(done.get(), true);
        Ok(())
    }).unwrap();
}

#[test]
fn eval_int() {
    gj::EventLoop::top_level(|wait_scope| {
        let promise : gj::Promise<u64, Box<::std::error::Error>> =
            gj::Promise::fulfilled(19u64).map(|x| {
                assert_eq!(x, 19);
                Ok(x + 2)
            });
        let value = promise.wait(wait_scope).unwrap();
        assert_eq!(value, 21);
        Ok(())
    }).unwrap();
}

#[test]
fn fulfiller() {
    gj::EventLoop::top_level(|wait_scope| {
        let (promise, fulfiller) = gj::new_promise_and_fulfiller::<u32, Box<::std::error::Error>>();
        let p1 = promise.map(|x| {
            assert_eq!(x, 10);
            return Ok(x + 1);
        });

        fulfiller.fulfill(10);
        let value = p1.wait(wait_scope).unwrap();
        assert_eq!(value, 11);
        Ok(())
    }).unwrap();
}

#[test]
fn chain() {
    gj::EventLoop::top_level(|wait_scope| {

        let promise: gj::Promise<i32, Box<::std::error::Error>> = gj::Promise::fulfilled(()).map(|()| { return Ok(123); });
        let promise2: gj::Promise<i32, Box<::std::error::Error>> = gj::Promise::fulfilled(()).map(|()| { return Ok(321); });

        let promise3 = promise.then(move |i| {
            return Ok(promise2.then(move |j| {
                return Ok(gj::Promise::fulfilled(i + j));
            }));
        });

        let value = promise3.wait(wait_scope).unwrap();
        assert_eq!(444, value);
        Ok(())
    }).unwrap();
}

#[test]
fn chain_error() {
    gj::EventLoop::top_level(|wait_scope| {

        let promise: gj::Promise<&'static str, Box<::std::error::Error>> =
            gj::Promise::fulfilled(()).map(|()| { Ok("123") });
        let promise2: gj::Promise<&'static str, Box<::std::error::Error>> =
            gj::Promise::fulfilled(()).map(|()| { Ok("XXX321") });

        let promise3 = promise.then(move |istr| {
            Ok(promise2.then(move |jstr| {
                let i: i32 = try!(istr.parse());
                let j: i32 = try!(jstr.parse());  // Should return an error.
                Ok(gj::Promise::fulfilled(i + j))
            }))
        });

        assert!(promise3.wait(wait_scope).is_err());
        Ok(())
    }).unwrap();
}

#[test]
fn deep_chain2() {
    gj::EventLoop::top_level(|wait_scope| {

        let mut promise: gj::Promise<u32, Box<::std::error::Error>> = gj::Promise::fulfilled(4u32);

        for _ in 0..1000 {
            promise = gj::Promise::fulfilled(()).then(|_| {
                Ok(promise)
            });
        }

        let value = promise.wait(wait_scope).unwrap();

        assert_eq!(value, 4);
        Ok(())
    }).unwrap();
}

#[test]
fn separate_fulfiller_chained() {
    gj::EventLoop::top_level(|wait_scope| {

        let (promise, fulfiller) = gj::new_promise_and_fulfiller::<gj::Promise<i32, Box<::std::error::Error>>, Box<::std::error::Error>>();
        let (inner_promise, inner_fulfiller) = gj::new_promise_and_fulfiller::<i32, Box<::std::error::Error>>();

        fulfiller.fulfill(inner_promise);
        inner_fulfiller.fulfill(123);

        let value = promise.wait(wait_scope).unwrap()
            .wait(wait_scope).unwrap(); // KJ gets away with only one wait() here.
        assert_eq!(value, 123);
        Ok(())
    }).unwrap();
}

#[test]
fn ordering() {
    use std::rc::Rc;
    use std::cell::{Cell, RefCell};

    gj::EventLoop::top_level(|wait_scope| {

        let counter = Rc::new(Cell::new(0u32));
        let (counter0, counter1, counter2, counter3, counter4, counter5, counter6) =
            (counter.clone(), counter.clone(), counter.clone(), counter.clone(), counter.clone(),
             counter.clone(), counter.clone());

        let mut promises: Vec<Rc<RefCell<Option<gj::Promise<(), Box<::std::error::Error>>>>>> = Vec::new();
        for _ in 0..6 {
            promises.push(Rc::new(RefCell::new(None)));
        }

        let promise2 = promises[2].clone();
        let promise3 = promises[3].clone();
        let promise4 = promises[4].clone();
        let promise5 = promises[5].clone();
        *promises[1].borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
            assert_eq!(counter0.get(), 0);
            counter0.set(1);

            {
                // Use a promise and fulfiller so that we can fulfill the promise after waiting on it in
                // order to induce depth-first scheduling.
                let (promise, fulfiller) = gj::new_promise_and_fulfiller::<(), Box<::std::error::Error>>();
                *promise2.borrow_mut() = Some(promise.then(move |_| {
                    assert_eq!(counter1.get(), 1);
                    counter1.set(2);
                    return Ok(gj::Promise::fulfilled(()));
                }));
                fulfiller.fulfill(());
            }

            // .map() is scheduled breadth-first if the promise has already resolved, but depth-first
            // if the promise resolves later.
            *promise3.borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
                assert_eq!(counter4.get(), 4); // XXX
                counter4.set(5);
                return Ok(gj::Promise::fulfilled(()));
            }).map(move |_| {
                assert_eq!(counter5.get(), 5);
                counter5.set(6);
                return Ok(());
            }));

            {
                let (promise, fulfiller) = gj::new_promise_and_fulfiller::<(), Box<::std::error::Error>>();
                *promise4.borrow_mut() = Some(promise.then(move |_| {
                    assert_eq!(counter2.get(), 2);
                    counter2.set(3);
                    return Ok(gj::Promise::fulfilled(()));
                }));
                fulfiller.fulfill(());
            }

            *promise5.borrow_mut() = Some(gj::Promise::fulfilled(()).map(move |_| {
                assert_eq!(counter6.get(), 6);
                counter6.set(7);
                return Ok(());
            }));

            return Ok(gj::Promise::fulfilled(()));
        }));

        *promises[0].borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
            assert_eq!(counter3.get(), 3);
            counter3.set(4);
            return Ok(gj::Promise::fulfilled(()));
        }));

        for p in promises.into_iter() {
            let maybe_p = ::std::mem::replace(&mut *p.borrow_mut(), None);
            match maybe_p {
                None => {}
                Some(p) => {
                    p.wait(wait_scope).unwrap()
                }
            }
        }

        assert_eq!(counter.get(), 7);
        Ok(())
    }).unwrap();
}

pub struct TaskReaperImpl {
    error_count: ::std::rc::Rc<::std::cell::Cell<u32>>,
}

impl gj::TaskReaper<(), Box<::std::error::Error>> for TaskReaperImpl {
    fn task_failed(&mut self, _error: Box<::std::error::Error>) {
        self.error_count.set(self.error_count.get() + 1);
    }
}

#[test]
fn task_set() {
    gj::EventLoop::top_level(|wait_scope| {
        let error_count = ::std::rc::Rc::new(::std::cell::Cell::new(0));
        let mut tasks = gj::TaskSet::new(Box::new(TaskReaperImpl {error_count: error_count.clone()}));
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Ok(())
        }));
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Fake IO Error"))
        }).lift());
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Ok(())
        }));

        gj::Promise::fulfilled(()).then(|()| -> Result<gj::Promise<(), Box<::std::error::Error>>, Box<::std::error::Error>> {
            panic!("Promise without waiter shouldn't execute.");
        });

        gj::Promise::fulfilled(()).map(|()| -> Result<(), Box<::std::error::Error>> {
            panic!("Promise without waiter shouldn't execute.");
        });

        gj::Promise::<(), Box<::std::error::Error>>::fulfilled(()).map(|()| { Ok(()) } ).wait(wait_scope).unwrap();

        assert_eq!(error_count.get(), 1);
        Ok(())
    }).unwrap();
}

#[test]
fn array_join() {
    gj::EventLoop::top_level(|wait_scope| {
        let promises: Vec<gj::Promise<u32, Box<::std::error::Error>>> =
            vec![gj::Promise::fulfilled(123),
                 gj::Promise::fulfilled(456),
                 gj::Promise::fulfilled(789)];

        let promise = gj::join_promises(promises);
        let result = promise.wait(wait_scope).unwrap();

        assert_eq!(result.len(), 3);
        assert_eq!(result[0], 123);
        assert_eq!(result[1], 456);
        assert_eq!(result[2], 789);
        Ok(())
    }).unwrap();
}

#[test]
fn exclusive_join() {
    gj::EventLoop::top_level(|wait_scope| {
        let left = gj::Promise::fulfilled(()).map(|()| {
            return Ok(123);
        });
        let (right, _) = gj::new_promise_and_fulfiller::<u32, Box<::std::error::Error>>();
        let result = left.exclusive_join(right).wait(wait_scope).unwrap();

        assert_eq!(result, 123);
        Ok(())
    }).unwrap();

    gj::EventLoop::top_level(|wait_scope| {
        let (left, _) = gj::new_promise_and_fulfiller::<u32, Box<::std::error::Error>>();
        let right = gj::Promise::fulfilled(()).map(|()| {
            return Ok(456);
        });

        let result = left.exclusive_join(right).wait(wait_scope).unwrap();

        assert_eq!(result, 456);
        Ok(())
    }).unwrap();

    gj::EventLoop::top_level(|wait_scope| {
        let left: gj::Promise<u32, Box<::std::error::Error>> = gj::Promise::fulfilled(()).map(|()| {
            Ok(123)
        });
        let right: gj::Promise<u32, Box<::std::error::Error>> = gj::Promise::fulfilled(()).map(|()| {
            Ok(456)
        }); // need to eagerly evaluate?

        let _result = left.exclusive_join(right).wait(wait_scope).unwrap();

//        assert_eq!(result, 456);
        Ok(())
    }).unwrap();
}
<commit_msg>Simplify types in tests.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

extern crate gj;

#[test]
fn eval_void() {
    use std::rc::Rc;
    use std::cell::Cell;
    gj::EventLoop::top_level(|wait_scope| {
        let done = Rc::new(Cell::new(false));
        let done1 = done.clone();
        let promise: gj::Promise<(), ()> =
            gj::Promise::fulfilled(()).map(move |()| {
                done1.clone().set(true);
                Ok(())
            });
        assert_eq!(done.get(), false);
        promise.wait(wait_scope).unwrap();
        assert_eq!(done.get(), true);
        Ok(())
    }).unwrap();
}

#[test]
fn eval_int() {
    gj::EventLoop::top_level(|wait_scope| {
        let promise: gj::Promise<u64, ()> =
            gj::Promise::fulfilled(19u64).map(|x| {
                assert_eq!(x, 19);
                Ok(x + 2)
            });
        let value = promise.wait(wait_scope).unwrap();
        assert_eq!(value, 21);
        Ok(())
    }).unwrap();
}

#[test]
fn fulfiller() {
    gj::EventLoop::top_level(|wait_scope| {
        let (promise, fulfiller) = gj::new_promise_and_fulfiller::<u32, ()>();
        let p1 = promise.map(|x| {
            assert_eq!(x, 10);
            return Ok(x + 1);
        });

        fulfiller.fulfill(10);
        let value = p1.wait(wait_scope).unwrap();
        assert_eq!(value, 11);
        Ok(())
    }).unwrap();
}

#[test]
fn chain() {
    gj::EventLoop::top_level(|wait_scope| {

        let promise: gj::Promise<i32, ()> = gj::Promise::fulfilled(()).map(|()| { return Ok(123); });
        let promise2: gj::Promise<i32, ()> = gj::Promise::fulfilled(()).map(|()| { return Ok(321); });

        let promise3 = promise.then(move |i| {
            return Ok(promise2.then(move |j| {
                return Ok(gj::Promise::fulfilled(i + j));
            }));
        });

        let value = promise3.wait(wait_scope).unwrap();
        assert_eq!(444, value);
        Ok(())
    }).unwrap();
}

#[test]
fn chain_error() {
    gj::EventLoop::top_level(|wait_scope| {

        let promise = gj::Promise::fulfilled(()).map(|()| { Ok("123") });
        let promise2: gj::Promise<&'static str, Box<::std::error::Error>> =
            gj::Promise::fulfilled(()).map(|()| { Ok("XXX321") });

        let promise3 = promise.then(move |istr| {
            Ok(promise2.then(move |jstr| {
                let i: i32 = try!(istr.parse());
                let j: i32 = try!(jstr.parse());  // Should return an error.
                Ok(gj::Promise::fulfilled(i + j))
            }))
        });

        assert!(promise3.wait(wait_scope).is_err());
        Ok(())
    }).unwrap();
}

#[test]
fn deep_chain2() {
    gj::EventLoop::top_level(|wait_scope| {

        let mut promise: gj::Promise<u32, ()> = gj::Promise::fulfilled(4u32);

        for _ in 0..1000 {
            promise = gj::Promise::fulfilled(()).then(|_| {
                Ok(promise)
            });
        }

        let value = promise.wait(wait_scope).unwrap();

        assert_eq!(value, 4);
        Ok(())
    }).unwrap();
}

#[test]
fn separate_fulfiller_chained() {
    gj::EventLoop::top_level(|wait_scope| {

        let (promise, fulfiller) = gj::new_promise_and_fulfiller::<gj::Promise<i32, ()>, ()>();
        let (inner_promise, inner_fulfiller) = gj::new_promise_and_fulfiller::<i32, ()>();

        fulfiller.fulfill(inner_promise);
        inner_fulfiller.fulfill(123);

        let value = promise.wait(wait_scope).unwrap()
            .wait(wait_scope).unwrap(); // KJ gets away with only one wait() here.
        assert_eq!(value, 123);
        Ok(())
    }).unwrap();
}

#[test]
fn ordering() {
    use std::rc::Rc;
    use std::cell::{Cell, RefCell};

    gj::EventLoop::top_level(|wait_scope| {

        let counter = Rc::new(Cell::new(0u32));
        let (counter0, counter1, counter2, counter3, counter4, counter5, counter6) =
            (counter.clone(), counter.clone(), counter.clone(), counter.clone(), counter.clone(),
             counter.clone(), counter.clone());

        let mut promises: Vec<Rc<RefCell<Option<gj::Promise<(), ()>>>>> = Vec::new();
        for _ in 0..6 {
            promises.push(Rc::new(RefCell::new(None)));
        }

        let promise2 = promises[2].clone();
        let promise3 = promises[3].clone();
        let promise4 = promises[4].clone();
        let promise5 = promises[5].clone();
        *promises[1].borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
            assert_eq!(counter0.get(), 0);
            counter0.set(1);

            {
                // Use a promise and fulfiller so that we can fulfill the promise after waiting on it in
                // order to induce depth-first scheduling.
                let (promise, fulfiller) = gj::new_promise_and_fulfiller::<(), ()>();
                *promise2.borrow_mut() = Some(promise.then(move |_| {
                    assert_eq!(counter1.get(), 1);
                    counter1.set(2);
                    return Ok(gj::Promise::fulfilled(()));
                }));
                fulfiller.fulfill(());
            }

            // .map() is scheduled breadth-first if the promise has already resolved, but depth-first
            // if the promise resolves later.
            *promise3.borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
                assert_eq!(counter4.get(), 4); // XXX
                counter4.set(5);
                return Ok(gj::Promise::fulfilled(()));
            }).map(move |_| {
                assert_eq!(counter5.get(), 5);
                counter5.set(6);
                return Ok(());
            }));

            {
                let (promise, fulfiller) = gj::new_promise_and_fulfiller::<(), ()>();
                *promise4.borrow_mut() = Some(promise.then(move |_| {
                    assert_eq!(counter2.get(), 2);
                    counter2.set(3);
                    return Ok(gj::Promise::fulfilled(()));
                }));
                fulfiller.fulfill(());
            }

            *promise5.borrow_mut() = Some(gj::Promise::fulfilled(()).map(move |_| {
                assert_eq!(counter6.get(), 6);
                counter6.set(7);
                return Ok(());
            }));

            return Ok(gj::Promise::fulfilled(()));
        }));

        *promises[0].borrow_mut() = Some(gj::Promise::fulfilled(()).then(move |_| {
            assert_eq!(counter3.get(), 3);
            counter3.set(4);
            return Ok(gj::Promise::fulfilled(()));
        }));

        for p in promises.into_iter() {
            let maybe_p = ::std::mem::replace(&mut *p.borrow_mut(), None);
            match maybe_p {
                None => {}
                Some(p) => {
                    p.wait(wait_scope).unwrap()
                }
            }
        }

        assert_eq!(counter.get(), 7);
        Ok(())
    }).unwrap();
}

pub struct TaskReaperImpl {
    error_count: ::std::rc::Rc<::std::cell::Cell<u32>>,
}

impl gj::TaskReaper<(), Box<::std::error::Error>> for TaskReaperImpl {
    fn task_failed(&mut self, _error: Box<::std::error::Error>) {
        self.error_count.set(self.error_count.get() + 1);
    }
}

#[test]
fn task_set() {
    gj::EventLoop::top_level(|wait_scope| {
        let error_count = ::std::rc::Rc::new(::std::cell::Cell::new(0));
        let mut tasks = gj::TaskSet::new(Box::new(TaskReaperImpl {error_count: error_count.clone()}));
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Ok(())
        }));
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Err(::std::io::Error::new(::std::io::ErrorKind::Other, "Fake IO Error"))
        }).lift());
        tasks.add(gj::Promise::fulfilled(()).map(|()| {
            Ok(())
        }));

        gj::Promise::fulfilled(()).then(|()| -> Result<gj::Promise<(), ()>, ()> {
            panic!("Promise without waiter shouldn't execute.");
        });

        gj::Promise::fulfilled(()).map(|()| -> Result<(), ()> {
            panic!("Promise without waiter shouldn't execute.");
        });

        gj::Promise::<(), ()>::fulfilled(()).map(|()| { Ok(()) } ).wait(wait_scope).unwrap();

        assert_eq!(error_count.get(), 1);
        Ok(())
    }).unwrap();
}

#[test]
fn array_join() {
    gj::EventLoop::top_level(|wait_scope| {
        let promises: Vec<gj::Promise<u32, ()>> =
            vec![gj::Promise::fulfilled(123),
                 gj::Promise::fulfilled(456),
                 gj::Promise::fulfilled(789)];

        let promise = gj::join_promises(promises);
        let result = promise.wait(wait_scope).unwrap();

        assert_eq!(result.len(), 3);
        assert_eq!(result[0], 123);
        assert_eq!(result[1], 456);
        assert_eq!(result[2], 789);
        Ok(())
    }).unwrap();
}

#[test]
fn exclusive_join() {
    gj::EventLoop::top_level(|wait_scope| {
        let left = gj::Promise::fulfilled(()).map(|()| {
            return Ok(123);
        });
        let (right, _) = gj::new_promise_and_fulfiller::<u32, ()>();
        let result = left.exclusive_join(right).wait(wait_scope).unwrap();

        assert_eq!(result, 123);
        Ok(())
    }).unwrap();

    gj::EventLoop::top_level(|wait_scope| {
        let (left, _) = gj::new_promise_and_fulfiller::<u32, ()>();
        let right = gj::Promise::fulfilled(()).map(|()| {
            return Ok(456);
        });

        let result = left.exclusive_join(right).wait(wait_scope).unwrap();

        assert_eq!(result, 456);
        Ok(())
    }).unwrap();

    gj::EventLoop::top_level(|wait_scope| {
        let left: gj::Promise<u32, ()> = gj::Promise::fulfilled(()).map(|()| {
            Ok(123)
        });
        let right: gj::Promise<u32, ()> = gj::Promise::fulfilled(()).map(|()| {
            Ok(456)
        }); // need to eagerly evaluate?

        let _result = left.exclusive_join(right).wait(wait_scope).unwrap();

//        assert_eq!(result, 456);
        Ok(())
    }).unwrap();
}
<|endoftext|>


<commit_before>mod common;

use rand::{thread_rng, Rng};

use sled::*;

use sled::{
    pin, BatchManifest, Log, LogKind, LogRead, Lsn, PageId, SEG_HEADER_LEN,
};

const PID: PageId = 4;
const REPLACE: LogKind = LogKind::Replace;

#[test]
#[ignore = "adding 50 causes the flush to never return"]
fn log_writebatch() -> crate::Result<()> {
    common::setup_logger();
    let config = Config::new().temporary(true);
    let db = config.open()?;
    let log = &db.context.pagecache.log;

    let guard = pin();

    log.reserve(REPLACE, PID, &IVec::from(b"1"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"2"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"3"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"4"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"5"), &guard)?.complete()?;

    // simulate a torn batch by
    // writing an LSN higher than
    // is possible to recover into
    // a batch manifest before
    // some writes.
    let batch_res =
        log.reserve(REPLACE, PID, &BatchManifest::default(), &guard)?;
    log.reserve(REPLACE, PID, &IVec::from(b"6"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"7"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"8"), &guard)?.complete()?;
    let last_res = log.reserve(REPLACE, PID, &IVec::from(b"9"), &guard)?;
    let last_res_lsn = last_res.lsn;
    last_res.complete()?;
    batch_res.mark_writebatch(last_res_lsn + 50)?;
    log.reserve(REPLACE, PID, &IVec::from(b"10"), &guard)?.complete()?;

    let mut iter = log.iter_from(0);

    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert_eq!(iter.next(), None);

    Ok(())
}

#[test]
fn more_log_reservations_than_buffers() -> Result<()> {
    let config = Config::new().temporary(true).segment_size(256);

    let db = config.open()?;
    let log = &db.context.pagecache.log;
    let mut reservations = vec![];

    let total_seg_overhead = SEG_HEADER_LEN;
    let big_msg_overhead = MAX_MSG_HEADER_LEN + total_seg_overhead;
    let big_msg_sz = config.segment_size - big_msg_overhead;

    for _ in 0..256 * 30 {
        let guard = pin();
        reservations.push(
            log.reserve(REPLACE, PID, &IVec::from(vec![0; big_msg_sz]), &guard)
                .unwrap(),
        )
    }
    for res in reservations.into_iter().rev() {
        // abort in reverse order
        res.abort()?;
    }

    log.flush()?;
    Ok(())
}

#[test]
fn non_contiguous_log_flush() -> Result<()> {
    let config = Config::new().temporary(true).segment_size(1024);

    let db = config.open()?;
    let log = &db.context.pagecache.log;

    let seg_overhead = SEG_HEADER_LEN;
    let buf_len = config.segment_size - (MAX_MSG_HEADER_LEN + seg_overhead);

    let guard = pin();
    let res1 = log
        .reserve(REPLACE, PID, &IVec::from(vec![0; buf_len]), &guard)
        .unwrap();
    let res2 = log
        .reserve(REPLACE, PID, &IVec::from(vec![0; buf_len]), &guard)
        .unwrap();
    let lsn = res2.lsn;
    res2.abort()?;
    res1.abort()?;
    log.make_stable(lsn)?;
    Ok(())
}

#[test]
#[cfg(not(miri))] // can't create threads
fn concurrent_logging() -> Result<()> {
    use std::thread;

    common::setup_logger();
    for _ in 0..10 {
        let config = Config::new()
            .temporary(true)
            .flush_every_ms(Some(50))
            .segment_size(256);

        let db = config.open()?;

        let db2 = db.clone();
        let db3 = db.clone();
        let db4 = db.clone();
        let db5 = db.clone();
        let db6 = db.clone();

        let seg_overhead = SEG_HEADER_LEN;
        let buf_len = config.segment_size - (MAX_MSG_HEADER_LEN + seg_overhead);

        let t1 = thread::Builder::new()
            .name("c1".to_string())
            .spawn(move || {
                let log = &db.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![1; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t2 = thread::Builder::new()
            .name("c2".to_string())
            .spawn(move || {
                let log = &db2.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![2; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t3 = thread::Builder::new()
            .name("c3".to_string())
            .spawn(move || {
                let log = &db3.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![3; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t4 = thread::Builder::new()
            .name("c4".to_string())
            .spawn(move || {
                let log = &db4.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![4; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();
        let t5 = thread::Builder::new()
            .name("c5".to_string())
            .spawn(move || {
                let log = &db5.context.pagecache.log;
                for i in 0..1_000 {
                    let guard = pin();
                    let buf = IVec::from(vec![5; i % buf_len]);
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t6 = thread::Builder::new()
            .name("c6".to_string())
            .spawn(move || {
                let log = &db6.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![6; i % buf_len]);
                    let guard = pin();
                    let (lsn, _lid) = log
                        .reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                    log.make_stable(lsn).unwrap();
                }
            })
            .unwrap();

        t6.join().unwrap();
        t5.join().unwrap();
        t4.join().unwrap();
        t3.join().unwrap();
        t2.join().unwrap();
        t1.join().unwrap();
    }

    Ok(())
}

fn write(log: &Log) {
    let data_bytes = IVec::from(b"yoyoyoyo");
    let guard = pin();
    let (lsn, ptr) = log
        .reserve(REPLACE, PID, &data_bytes, &guard)
        .unwrap()
        .complete()
        .unwrap();
    let read_buf = log.read(PID, lsn, ptr).unwrap().into_data().unwrap();
    assert_eq!(
        *read_buf,
        *data_bytes.serialize(),
        "after writing data, it should be readable"
    );
}

fn abort(log: &Log) {
    let guard = pin();
    let res = log.reserve(REPLACE, PID, &IVec::from(&[0; 5]), &guard).unwrap();
    let (lsn, ptr) = res.abort().unwrap();
    match log.read(PID, lsn, ptr) {
        Ok(LogRead::Canceled(_)) => {}
        other => {
            panic!(
                "expected to successfully read \
                 aborted log message, instead read {:?}",
                other
            );
        }
    }
}

#[test]
fn log_aborts() {
    common::setup_logger();
    let config = Config::new().temporary(true);
    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;
    write(&log);
    abort(&log);
    write(&log);
    abort(&log);
    write(&log);
    abort(&log);
}

#[test]
#[cfg_attr(any(target_os = "fuchsia", miri), ignore)]
fn log_chunky_iterator() {
    common::setup_logger();
    let config =
        Config::new().flush_every_ms(None).temporary(true).segment_size(256);

    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;

    let mut reference = vec![];

    let max_valid_size =
        config.segment_size - (MAX_MSG_HEADER_LEN + SEG_HEADER_LEN);

    for i in PID..1000 {
        let len = thread_rng().gen_range(0, max_valid_size * 2);
        let item = thread_rng().gen::<u8>();
        let buf = IVec::from(vec![item; len]);
        let abort = thread_rng().gen::<bool>();

        let pid = 10000 + i;

        let guard = pin();

        if abort {
            let res = log
                .reserve(REPLACE, pid, &buf, &guard)
                .expect("should be able to reserve");
            res.abort().unwrap();
        } else {
            let res = log
                .reserve(REPLACE, pid, &buf, &guard)
                .expect("should be able to write reservation");
            let ptr = res.pointer;
            let (lsn, _) = res.complete().unwrap();
            reference.push((REPLACE, pid, lsn, ptr));
        }
    }

    for (_, pid, lsn, ptr) in reference.into_iter() {
        assert!(log.read(pid, lsn, ptr).is_ok());
    }
}

#[test]
fn multi_segment_log_iteration() -> Result<()> {
    common::setup_logger();
    // ensure segments are being linked
    // ensure trailers are valid
    let config = Config::new().temporary(true).segment_size(512);

    let total_seg_overhead = SEG_HEADER_LEN;
    let big_msg_overhead = MAX_MSG_HEADER_LEN + total_seg_overhead;
    let big_msg_sz = (config.segment_size - big_msg_overhead) / 64;

    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;

    for i in 0..48 {
        let buf = IVec::from(vec![i as u8; big_msg_sz * i]);
        let guard = pin();
        log.reserve(REPLACE, i as PageId, &buf, &guard)
            .unwrap()
            .complete()
            .unwrap();
    }
    log.flush()?;

    // start iterating just past the first segment header
    let mut iter = log.iter_from(SEG_HEADER_LEN as Lsn);

    for _ in 0..48 {
        iter.next().expect("expected to read another message");
    }

    Ok(())
}
<commit_msg>Improve previously flaky multi_segment_log_iteration test<commit_after>mod common;

use rand::{thread_rng, Rng};

use sled::*;

use sled::{
    pin, BatchManifest, Log, LogKind, LogRead, Lsn, PageId, SEG_HEADER_LEN,
};

const PID: PageId = 4;
const REPLACE: LogKind = LogKind::Replace;

#[test]
#[ignore = "adding 50 causes the flush to never return"]
fn log_writebatch() -> crate::Result<()> {
    common::setup_logger();
    let config = Config::new().temporary(true);
    let db = config.open()?;
    let log = &db.context.pagecache.log;

    let guard = pin();

    log.reserve(REPLACE, PID, &IVec::from(b"1"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"2"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"3"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"4"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"5"), &guard)?.complete()?;

    // simulate a torn batch by
    // writing an LSN higher than
    // is possible to recover into
    // a batch manifest before
    // some writes.
    let batch_res =
        log.reserve(REPLACE, PID, &BatchManifest::default(), &guard)?;
    log.reserve(REPLACE, PID, &IVec::from(b"6"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"7"), &guard)?.complete()?;
    log.reserve(REPLACE, PID, &IVec::from(b"8"), &guard)?.complete()?;
    let last_res = log.reserve(REPLACE, PID, &IVec::from(b"9"), &guard)?;
    let last_res_lsn = last_res.lsn;
    last_res.complete()?;
    batch_res.mark_writebatch(last_res_lsn + 50)?;
    log.reserve(REPLACE, PID, &IVec::from(b"10"), &guard)?.complete()?;

    let mut iter = log.iter_from(0);

    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert_eq!(iter.next(), None);

    Ok(())
}

#[test]
fn more_log_reservations_than_buffers() -> Result<()> {
    let config = Config::new().temporary(true).segment_size(256);

    let db = config.open()?;
    let log = &db.context.pagecache.log;
    let mut reservations = vec![];

    let total_seg_overhead = SEG_HEADER_LEN;
    let big_msg_overhead = MAX_MSG_HEADER_LEN + total_seg_overhead;
    let big_msg_sz = config.segment_size - big_msg_overhead;

    for _ in 0..256 * 30 {
        let guard = pin();
        reservations.push(
            log.reserve(REPLACE, PID, &IVec::from(vec![0; big_msg_sz]), &guard)
                .unwrap(),
        )
    }
    for res in reservations.into_iter().rev() {
        // abort in reverse order
        res.abort()?;
    }

    log.flush()?;
    Ok(())
}

#[test]
fn non_contiguous_log_flush() -> Result<()> {
    let config = Config::new().temporary(true).segment_size(1024);

    let db = config.open()?;
    let log = &db.context.pagecache.log;

    let seg_overhead = SEG_HEADER_LEN;
    let buf_len = config.segment_size - (MAX_MSG_HEADER_LEN + seg_overhead);

    let guard = pin();
    let res1 = log
        .reserve(REPLACE, PID, &IVec::from(vec![0; buf_len]), &guard)
        .unwrap();
    let res2 = log
        .reserve(REPLACE, PID, &IVec::from(vec![0; buf_len]), &guard)
        .unwrap();
    let lsn = res2.lsn;
    res2.abort()?;
    res1.abort()?;
    log.make_stable(lsn)?;
    Ok(())
}

#[test]
#[cfg(not(miri))] // can't create threads
fn concurrent_logging() -> Result<()> {
    use std::thread;

    common::setup_logger();
    for _ in 0..10 {
        let config = Config::new()
            .temporary(true)
            .flush_every_ms(Some(50))
            .segment_size(256);

        let db = config.open()?;

        let db2 = db.clone();
        let db3 = db.clone();
        let db4 = db.clone();
        let db5 = db.clone();
        let db6 = db.clone();

        let seg_overhead = SEG_HEADER_LEN;
        let buf_len = config.segment_size - (MAX_MSG_HEADER_LEN + seg_overhead);

        let t1 = thread::Builder::new()
            .name("c1".to_string())
            .spawn(move || {
                let log = &db.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![1; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t2 = thread::Builder::new()
            .name("c2".to_string())
            .spawn(move || {
                let log = &db2.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![2; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t3 = thread::Builder::new()
            .name("c3".to_string())
            .spawn(move || {
                let log = &db3.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![3; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t4 = thread::Builder::new()
            .name("c4".to_string())
            .spawn(move || {
                let log = &db4.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![4; i % buf_len]);
                    let guard = pin();
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();
        let t5 = thread::Builder::new()
            .name("c5".to_string())
            .spawn(move || {
                let log = &db5.context.pagecache.log;
                for i in 0..1_000 {
                    let guard = pin();
                    let buf = IVec::from(vec![5; i % buf_len]);
                    log.reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                }
            })
            .unwrap();

        let t6 = thread::Builder::new()
            .name("c6".to_string())
            .spawn(move || {
                let log = &db6.context.pagecache.log;
                for i in 0..1_000 {
                    let buf = IVec::from(vec![6; i % buf_len]);
                    let guard = pin();
                    let (lsn, _lid) = log
                        .reserve(REPLACE, PID, &buf, &guard)
                        .unwrap()
                        .complete()
                        .unwrap();
                    log.make_stable(lsn).unwrap();
                }
            })
            .unwrap();

        t6.join().unwrap();
        t5.join().unwrap();
        t4.join().unwrap();
        t3.join().unwrap();
        t2.join().unwrap();
        t1.join().unwrap();
    }

    Ok(())
}

fn write(log: &Log) {
    let data_bytes = IVec::from(b"yoyoyoyo");
    let guard = pin();
    let (lsn, ptr) = log
        .reserve(REPLACE, PID, &data_bytes, &guard)
        .unwrap()
        .complete()
        .unwrap();
    let read_buf = log.read(PID, lsn, ptr).unwrap().into_data().unwrap();
    assert_eq!(
        *read_buf,
        *data_bytes.serialize(),
        "after writing data, it should be readable"
    );
}

fn abort(log: &Log) {
    let guard = pin();
    let res = log.reserve(REPLACE, PID, &IVec::from(&[0; 5]), &guard).unwrap();
    let (lsn, ptr) = res.abort().unwrap();
    match log.read(PID, lsn, ptr) {
        Ok(LogRead::Canceled(_)) => {}
        other => {
            panic!(
                "expected to successfully read \
                 aborted log message, instead read {:?}",
                other
            );
        }
    }
}

#[test]
fn log_aborts() {
    common::setup_logger();
    let config = Config::new().temporary(true);
    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;
    write(&log);
    abort(&log);
    write(&log);
    abort(&log);
    write(&log);
    abort(&log);
}

#[test]
#[cfg_attr(any(target_os = "fuchsia", miri), ignore)]
fn log_chunky_iterator() {
    common::setup_logger();
    let config =
        Config::new().flush_every_ms(None).temporary(true).segment_size(256);

    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;

    let mut reference = vec![];

    let max_valid_size =
        config.segment_size - (MAX_MSG_HEADER_LEN + SEG_HEADER_LEN);

    for i in PID..1000 {
        let len = thread_rng().gen_range(0, max_valid_size * 2);
        let item = thread_rng().gen::<u8>();
        let buf = IVec::from(vec![item; len]);
        let abort = thread_rng().gen::<bool>();

        let pid = 10000 + i;

        let guard = pin();

        if abort {
            let res = log
                .reserve(REPLACE, pid, &buf, &guard)
                .expect("should be able to reserve");
            res.abort().unwrap();
        } else {
            let res = log
                .reserve(REPLACE, pid, &buf, &guard)
                .expect("should be able to write reservation");
            let ptr = res.pointer;
            let (lsn, _) = res.complete().unwrap();
            reference.push((REPLACE, pid, lsn, ptr));
        }
    }

    for (_, pid, lsn, ptr) in reference.into_iter() {
        assert!(log.read(pid, lsn, ptr).is_ok());
    }
}

#[test]
fn multi_segment_log_iteration() -> Result<()> {
    common::setup_logger();
    // ensure segments are being linked
    // ensure trailers are valid
    let config =
        Config::new().temporary(true).segment_size(512).flush_every_ms(None);

    // this guard prevents any segments from being freed
    let _guard = pin();

    let total_seg_overhead = SEG_HEADER_LEN;
    let big_msg_overhead = MAX_MSG_HEADER_LEN + total_seg_overhead;
    let big_msg_sz = (config.segment_size - big_msg_overhead) / 64;

    let db = config.open().unwrap();
    let log = &db.context.pagecache.log;

    let mut expected_pids = std::collections::HashSet::new();

    for i in 4..1000 {
        let buf = IVec::from(vec![i as u8; big_msg_sz * i]);
        let guard = pin();
        let (lsn, _ptr) = log
            .reserve(REPLACE, i as PageId, &buf, &guard)
            .unwrap()
            .complete()
            .unwrap();

        expected_pids.insert(i as PageId);
    }

    db.flush();

    // start iterating just past the first segment header
    let mut iter = log.iter_from(SEG_HEADER_LEN as Lsn);

    while let Some((_, pid, _, _, _)) = iter.next() {
        if pid <= 3 {
            // this page is for the meta page, counter page, or the default
            // tree's leaf or index nodes
            continue;
        }
        assert!(
            expected_pids.remove(&pid),
            "read pid {} while iterating, but this was no longer expected",
            pid
        );
    }

    assert!(
        expected_pids.is_empty(),
        "expected to read pids {:?} but never saw them while iterating",
        expected_pids
    );

    Ok(())
}
<|endoftext|>


<commit_before>use std::{
    cell::RefCell,
    sync::{Arc, Mutex},
};

use wayland_server::{
    backend::{protocol::Message, ClientId, Handle, ObjectData, ObjectId},
    protocol::{
        wl_data_device_manager::DndAction,
        wl_data_offer::{self, WlDataOffer},
        wl_surface,
    },
    DisplayHandle, Resource,
};

use crate::wayland::seat::{
    AxisFrame, ButtonEvent, MotionEvent, PointerGrab, PointerGrabStartData, PointerInnerHandle, Seat,
};

use super::{DataDeviceHandler, SeatData, ServerDndGrabHandler, SourceMetadata};

pub(crate) struct ServerDnDGrab<D> {
    start_data: PointerGrabStartData,
    metadata: super::SourceMetadata,
    current_focus: Option<wl_surface::WlSurface>,
    pending_offers: Vec<wl_data_offer::WlDataOffer>,
    offer_data: Option<Arc<Mutex<ServerDndOfferData>>>,
    seat: Seat<D>,
}

impl<D> ServerDnDGrab<D> {
    pub(crate) fn new(
        start_data: PointerGrabStartData,
        metadata: super::SourceMetadata,
        seat: Seat<D>,
    ) -> Self {
        Self {
            start_data,
            metadata,
            current_focus: None,
            pending_offers: Vec::with_capacity(1),
            offer_data: None,
            seat,
        }
    }
}

impl<D> PointerGrab<D> for ServerDnDGrab<D>
where
    D: DataDeviceHandler,
    D: 'static,
{
    fn motion(
        &mut self,
        _data: &mut D,
        dh: &mut DisplayHandle<'_>,
        _handle: &mut PointerInnerHandle<'_, D>,
        event: &MotionEvent,
    ) {
        let focus = event.focus.clone();
        let location = event.location;
        let serial = event.serial;
        let time = event.time;

        let seat_data = self
            .seat
            .user_data()
            .get::<RefCell<SeatData>>()
            .unwrap()
            .borrow_mut();
        if focus.as_ref().map(|&(ref s, _)| s) != self.current_focus.as_ref() {
            // focus changed, we need to make a leave if appropriate
            if let Some(surface) = self.current_focus.take() {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.leave(dh);
                    }
                }
                // disable the offers
                self.pending_offers.clear();
                if let Some(offer_data) = self.offer_data.take() {
                    offer_data.lock().unwrap().active = false;
                }
            }
        }
        if let Some((surface, surface_location)) = focus {
            // early return if the surface is no longer valid
            let client = match dh.get_client(surface.id()) {
                Ok(c) => c,
                _ => return,
            };
            let (x, y) = (location - surface_location.to_f64()).into();
            if self.current_focus.is_none() {
                // We entered a new surface, send the data offer
                let offer_data = Arc::new(Mutex::new(ServerDndOfferData {
                    active: true,
                    dropped: false,
                    accepted: true,
                    chosen_action: DndAction::empty(),
                }));
                for device in seat_data
                    .known_devices()
                    .iter()
                    .filter(|d| d.id().same_client_as(&surface.id()))
                {
                    let handle = dh.backend_handle::<D>().unwrap();
                    // create a data offer
                    let offer = handle
                        .create_object(
                            client.id(),
                            WlDataOffer::interface(),
                            device.version(),
                            Arc::new(ServerDndData {
                                metadata: self.metadata.clone(),
                                ofer_data: offer_data.clone(),
                            }),
                        )
                        .unwrap();
                    let offer = WlDataOffer::from_id(dh, offer).unwrap();

                    // advertize the offer to the client
                    device.data_offer(dh, &offer);
                    for mime_type in self.metadata.mime_types.iter().cloned() {
                        offer.offer(dh, mime_type);
                    }
                    offer.source_actions(dh, self.metadata.dnd_action);
                    device.enter(dh, serial.into(), &surface, x, y, Some(&offer));
                    self.pending_offers.push(offer);
                }
                self.offer_data = Some(offer_data);
                self.current_focus = Some(surface);
            } else {
                // make a move
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.motion(dh, time, x, y);
                    }
                }
            }
        }
    }

    fn button(
        &mut self,
        data: &mut D,
        dh: &mut DisplayHandle<'_>,
        handle: &mut PointerInnerHandle<'_, D>,
        event: &ButtonEvent,
    ) {
        let serial = event.serial;
        let time = event.time;

        if handle.current_pressed().is_empty() {
            // the user dropped, proceed to the drop
            let seat_data = self
                .seat
                .user_data()
                .get::<RefCell<SeatData>>()
                .unwrap()
                .borrow_mut();
            let validated = if let Some(ref data) = self.offer_data {
                let data = data.lock().unwrap();
                data.accepted && (!data.chosen_action.is_empty())
            } else {
                false
            };
            if let Some(ref surface) = self.current_focus {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) && validated {
                        device.drop(dh);
                    }
                }
            }
            if let Some(ref offer_data) = self.offer_data {
                let mut data = offer_data.lock().unwrap();
                if validated {
                    data.dropped = true;
                } else {
                    data.active = false;
                }
            }

            ServerDndGrabHandler::dropped(data);
            if !validated {
                data.cancelled();
            }
            // in all cases abandon the drop
            // no more buttons are pressed, release the grab
            if let Some(ref surface) = self.current_focus {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.leave(dh);
                    }
                }
            }
            handle.unset_grab(dh, serial, time);
        }
    }

    fn axis(
        &mut self,
        _data: &mut D,
        dh: &mut DisplayHandle<'_>,
        handle: &mut PointerInnerHandle<'_, D>,
        details: AxisFrame,
    ) {
        // we just forward the axis events as is
        handle.axis(dh, details);
    }

    fn start_data(&self) -> &PointerGrabStartData {
        &self.start_data
    }
}

#[derive(Debug)]
struct ServerDndOfferData {
    active: bool,
    dropped: bool,
    accepted: bool,
    chosen_action: DndAction,
}

struct ServerDndData {
    metadata: SourceMetadata,
    ofer_data: Arc<Mutex<ServerDndOfferData>>,
}

impl<D> ObjectData<D> for ServerDndData
where
    D: DataDeviceHandler,
{
    fn request(
        self: Arc<Self>,
        dh: &mut Handle<D>,
        handler: &mut D,
        _client_id: ClientId,
        msg: Message<ObjectId>,
    ) -> Option<Arc<dyn ObjectData<D>>> {
        let mut dh = DisplayHandle::from(dh);

        if let Ok((resource, request)) = WlDataOffer::parse_request(&mut dh, msg) {
            handle_server_dnd(handler, &resource, request, &self, &mut dh);
        }

        None
    }

    fn destroyed(&self, _data: &mut D, _client_id: ClientId, _object_id: ObjectId) {}
}

fn handle_server_dnd<D>(
    handler: &mut D,
    offer: &WlDataOffer,
    request: wl_data_offer::Request,

    data: &ServerDndData,

    dh: &mut wayland_server::DisplayHandle<'_>,
) where
    D: DataDeviceHandler,
{
    use self::wl_data_offer::Request;

    let metadata = &data.metadata;
    let offer_data = &data.ofer_data;

    let mut data = offer_data.lock().unwrap();
    match request {
        Request::Accept { mime_type, .. } => {
            if let Some(mtype) = mime_type {
                data.accepted = metadata.mime_types.contains(&mtype);
            } else {
                data.accepted = false;
            }
        }
        Request::Receive { mime_type, fd } => {
            // check if the source and associated mime type is still valid
            if metadata.mime_types.contains(&mime_type) && data.active {
                handler.send(mime_type, fd);
            }
        }
        Request::Destroy => {}
        Request::Finish => {
            if !data.active {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish as u32,
                    "Cannot finish a data offer that is no longer active.",
                );
                return;
            }
            if !data.accepted {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer that has not been accepted.",
                );
                return;
            }
            if !data.dropped {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer that has not been dropped.",
                );
                return;
            }
            if data.chosen_action.is_empty() {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer with no valid action.",
                );
                return;
            }

            handler.finished();
            data.active = false;
        }
        Request::SetActions {
            dnd_actions,
            preferred_action,
        } => {
            let dnd_actions = dnd_actions.into_result().unwrap_or(DndAction::None);
            let preferred_action = preferred_action.into_result().unwrap_or(DndAction::None);

            // preferred_action must only contain one bitflag at the same time
            if ![DndAction::None, DndAction::Move, DndAction::Copy, DndAction::Ask]
                .contains(&preferred_action)
            {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidAction,
                    "Invalid preferred action.",
                );
                return;
            }
            let possible_actions = metadata.dnd_action & dnd_actions;
            data.chosen_action = handler.action_choice(possible_actions, preferred_action);
            // check that the user provided callback respects that one precise action should be chosen
            debug_assert!(
                [DndAction::None, DndAction::Move, DndAction::Copy, DndAction::Ask]
                    .contains(&data.chosen_action),
                "Only one precise action should be chosen"
            );
            offer.action(dh, data.chosen_action);

            handler.action(data.chosen_action);
        }
        _ => unreachable!(),
    }
}
<commit_msg>Fix formatting<commit_after>use std::{
    cell::RefCell,
    sync::{Arc, Mutex},
};

use wayland_server::{
    backend::{protocol::Message, ClientId, Handle, ObjectData, ObjectId},
    protocol::{
        wl_data_device_manager::DndAction,
        wl_data_offer::{self, WlDataOffer},
        wl_surface,
    },
    DisplayHandle, Resource,
};

use crate::wayland::seat::{
    AxisFrame, ButtonEvent, MotionEvent, PointerGrab, PointerGrabStartData, PointerInnerHandle, Seat,
};

use super::{DataDeviceHandler, SeatData, ServerDndGrabHandler, SourceMetadata};

pub(crate) struct ServerDnDGrab<D> {
    start_data: PointerGrabStartData,
    metadata: super::SourceMetadata,
    current_focus: Option<wl_surface::WlSurface>,
    pending_offers: Vec<wl_data_offer::WlDataOffer>,
    offer_data: Option<Arc<Mutex<ServerDndOfferData>>>,
    seat: Seat<D>,
}

impl<D> ServerDnDGrab<D> {
    pub(crate) fn new(
        start_data: PointerGrabStartData,
        metadata: super::SourceMetadata,
        seat: Seat<D>,
    ) -> Self {
        Self {
            start_data,
            metadata,
            current_focus: None,
            pending_offers: Vec::with_capacity(1),
            offer_data: None,
            seat,
        }
    }
}

impl<D> PointerGrab<D> for ServerDnDGrab<D>
where
    D: DataDeviceHandler,
    D: 'static,
{
    fn motion(
        &mut self,
        _data: &mut D,
        dh: &mut DisplayHandle<'_>,
        _handle: &mut PointerInnerHandle<'_, D>,
        event: &MotionEvent,
    ) {
        let focus = event.focus.clone();
        let location = event.location;
        let serial = event.serial;
        let time = event.time;

        let seat_data = self
            .seat
            .user_data()
            .get::<RefCell<SeatData>>()
            .unwrap()
            .borrow_mut();
        if focus.as_ref().map(|&(ref s, _)| s) != self.current_focus.as_ref() {
            // focus changed, we need to make a leave if appropriate
            if let Some(surface) = self.current_focus.take() {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.leave(dh);
                    }
                }
                // disable the offers
                self.pending_offers.clear();
                if let Some(offer_data) = self.offer_data.take() {
                    offer_data.lock().unwrap().active = false;
                }
            }
        }
        if let Some((surface, surface_location)) = focus {
            // early return if the surface is no longer valid
            let client = match dh.get_client(surface.id()) {
                Ok(c) => c,
                _ => return,
            };
            let (x, y) = (location - surface_location.to_f64()).into();
            if self.current_focus.is_none() {
                // We entered a new surface, send the data offer
                let offer_data = Arc::new(Mutex::new(ServerDndOfferData {
                    active: true,
                    dropped: false,
                    accepted: true,
                    chosen_action: DndAction::empty(),
                }));
                for device in seat_data
                    .known_devices()
                    .iter()
                    .filter(|d| d.id().same_client_as(&surface.id()))
                {
                    let handle = dh.backend_handle::<D>().unwrap();
                    // create a data offer
                    let offer = handle
                        .create_object(
                            client.id(),
                            WlDataOffer::interface(),
                            device.version(),
                            Arc::new(ServerDndData {
                                metadata: self.metadata.clone(),
                                ofer_data: offer_data.clone(),
                            }),
                        )
                        .unwrap();
                    let offer = WlDataOffer::from_id(dh, offer).unwrap();

                    // advertize the offer to the client
                    device.data_offer(dh, &offer);
                    for mime_type in self.metadata.mime_types.iter().cloned() {
                        offer.offer(dh, mime_type);
                    }
                    offer.source_actions(dh, self.metadata.dnd_action);
                    device.enter(dh, serial.into(), &surface, x, y, Some(&offer));
                    self.pending_offers.push(offer);
                }
                self.offer_data = Some(offer_data);
                self.current_focus = Some(surface);
            } else {
                // make a move
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.motion(dh, time, x, y);
                    }
                }
            }
        }
    }

    fn button(
        &mut self,
        data: &mut D,
        dh: &mut DisplayHandle<'_>,
        handle: &mut PointerInnerHandle<'_, D>,
        event: &ButtonEvent,
    ) {
        let serial = event.serial;
        let time = event.time;

        if handle.current_pressed().is_empty() {
            // the user dropped, proceed to the drop
            let seat_data = self
                .seat
                .user_data()
                .get::<RefCell<SeatData>>()
                .unwrap()
                .borrow_mut();
            let validated = if let Some(ref data) = self.offer_data {
                let data = data.lock().unwrap();
                data.accepted && (!data.chosen_action.is_empty())
            } else {
                false
            };
            if let Some(ref surface) = self.current_focus {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) && validated {
                        device.drop(dh);
                    }
                }
            }
            if let Some(ref offer_data) = self.offer_data {
                let mut data = offer_data.lock().unwrap();
                if validated {
                    data.dropped = true;
                } else {
                    data.active = false;
                }
            }

            ServerDndGrabHandler::dropped(data);
            if !validated {
                data.cancelled();
            }
            // in all cases abandon the drop
            // no more buttons are pressed, release the grab
            if let Some(ref surface) = self.current_focus {
                for device in seat_data.known_devices() {
                    if device.id().same_client_as(&surface.id()) {
                        device.leave(dh);
                    }
                }
            }
            handle.unset_grab(dh, serial, time);
        }
    }

    fn axis(
        &mut self,
        _data: &mut D,
        dh: &mut DisplayHandle<'_>,
        handle: &mut PointerInnerHandle<'_, D>,
        details: AxisFrame,
    ) {
        // we just forward the axis events as is
        handle.axis(dh, details);
    }

    fn start_data(&self) -> &PointerGrabStartData {
        &self.start_data
    }
}

#[derive(Debug)]
struct ServerDndOfferData {
    active: bool,
    dropped: bool,
    accepted: bool,
    chosen_action: DndAction,
}

struct ServerDndData {
    metadata: SourceMetadata,
    ofer_data: Arc<Mutex<ServerDndOfferData>>,
}

impl<D> ObjectData<D> for ServerDndData
where
    D: DataDeviceHandler,
{
    fn request(
        self: Arc<Self>,
        dh: &mut Handle<D>,
        handler: &mut D,
        _client_id: ClientId,
        msg: Message<ObjectId>,
    ) -> Option<Arc<dyn ObjectData<D>>> {
        let mut dh = DisplayHandle::from(dh);

        if let Ok((resource, request)) = WlDataOffer::parse_request(&mut dh, msg) {
            handle_server_dnd(handler, &resource, request, &self, &mut dh);
        }

        None
    }

    fn destroyed(&self, _data: &mut D, _client_id: ClientId, _object_id: ObjectId) {}
}

fn handle_server_dnd<D>(
    handler: &mut D,
    offer: &WlDataOffer,
    request: wl_data_offer::Request,
    data: &ServerDndData,
    dh: &mut wayland_server::DisplayHandle<'_>,
) where
    D: DataDeviceHandler,
{
    use self::wl_data_offer::Request;

    let metadata = &data.metadata;
    let offer_data = &data.ofer_data;

    let mut data = offer_data.lock().unwrap();
    match request {
        Request::Accept { mime_type, .. } => {
            if let Some(mtype) = mime_type {
                data.accepted = metadata.mime_types.contains(&mtype);
            } else {
                data.accepted = false;
            }
        }
        Request::Receive { mime_type, fd } => {
            // check if the source and associated mime type is still valid
            if metadata.mime_types.contains(&mime_type) && data.active {
                handler.send(mime_type, fd);
            }
        }
        Request::Destroy => {}
        Request::Finish => {
            if !data.active {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish as u32,
                    "Cannot finish a data offer that is no longer active.",
                );
                return;
            }
            if !data.accepted {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer that has not been accepted.",
                );
                return;
            }
            if !data.dropped {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer that has not been dropped.",
                );
                return;
            }
            if data.chosen_action.is_empty() {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidFinish,
                    "Cannot finish a data offer with no valid action.",
                );
                return;
            }

            handler.finished();
            data.active = false;
        }
        Request::SetActions {
            dnd_actions,
            preferred_action,
        } => {
            let dnd_actions = dnd_actions.into_result().unwrap_or(DndAction::None);
            let preferred_action = preferred_action.into_result().unwrap_or(DndAction::None);

            // preferred_action must only contain one bitflag at the same time
            if ![DndAction::None, DndAction::Move, DndAction::Copy, DndAction::Ask]
                .contains(&preferred_action)
            {
                offer.post_error(
                    dh,
                    wl_data_offer::Error::InvalidAction,
                    "Invalid preferred action.",
                );
                return;
            }
            let possible_actions = metadata.dnd_action & dnd_actions;
            data.chosen_action = handler.action_choice(possible_actions, preferred_action);
            // check that the user provided callback respects that one precise action should be chosen
            debug_assert!(
                [DndAction::None, DndAction::Move, DndAction::Copy, DndAction::Ask]
                    .contains(&data.chosen_action),
                "Only one precise action should be chosen"
            );
            offer.action(dh, data.chosen_action);

            handler.action(data.chosen_action);
        }
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::{Data, Container, Style};
use attr::{Identifier, EnumTag};
use Ctxt;

/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
    check_getter(cx, cont);
    check_identifier(cx, cont);
    check_variant_skip_attrs(cx, cont);
    check_internal_tag_field_name_conflict(cx, cont);
}

/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(_) => {
            if cont.data.has_getter() {
                cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
            }
        }
        Data::Struct(_, _) => {
            if cont.data.has_getter() && cont.attrs.remote().is_none() {
                cx.error(
                    "#[serde(getter = \"...\")] can only be used in structs \
                     that have #[serde(remote = \"...\")]",
                );
            }
        }
    }
}

/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for (i, variant) in variants.iter().enumerate() {
        match (
            variant.style,
            cont.attrs.identifier(),
            variant.attrs.other(),
        ) {
            // The `other` attribute may only be used in a field_identifier.
            (_, Identifier::Variant, true) | (_, Identifier::No, true) => {
                cx.error("#[serde(other)] may only be used inside a field_identifier");
            }

            // Variant with `other` attribute must be the last one.
            (Style::Unit, Identifier::Field, true) => {
                if i < variants.len() - 1 {
                    cx.error("#[serde(other)] must be the last variant");
                }
            }

            // Variant with `other` attribute must be a unit variant.
            (_, Identifier::Field, true) => {
                cx.error("#[serde(other)] must be on a unit variant");
            }

            // Any sort of variant is allowed if this is not an identifier.
            (_, Identifier::No, false) => {}

            // Unit variant without `other` attribute is always fine.
            (Style::Unit, _, false) => {}

            // The last field is allowed to be a newtype catch-all.
            (Style::Newtype, Identifier::Field, false) => {
                if i < variants.len() - 1 {
                    cx.error(format!("`{}` must be the last variant", variant.ident));
                }
            }

            (_, Identifier::Field, false) => {
                cx.error("field_identifier may only contain unit variants");
            }

            (_, Identifier::Variant, false) => {
                cx.error("variant_identifier may only contain unit variants");
            }
        }
    }
}

/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for variant in variants.iter() {
        if variant.attrs.serialize_with().is_some() {
            if variant.attrs.skip_serializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(serialize_with)] and \
                     #[serde(skip_serializing)]",
                    variant.ident
                ));
            }

            for (i, field) in variant.fields.iter().enumerate() {
                let ident = field
                    .ident
                    .as_ref()
                    .map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));

                if field.attrs.skip_serializing() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing)]",
                        variant.ident, ident
                    ));
                }

                if field.attrs.skip_serializing_if().is_some() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing_if)]",
                        variant.ident, ident
                    ));
                }
            }
        }

        if variant.attrs.deserialize_with().is_some() {
            if variant.attrs.skip_deserializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(deserialize_with)] and \
                     #[serde(skip_deserializing)]",
                    variant.ident
                ));
            }

            for (i, field) in variant.fields.iter().enumerate() {
                if field.attrs.skip_deserializing() {
                    let ident = field
                        .ident
                        .as_ref()
                        .map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));

                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(deserialize_with)] \
                         and a field {} marked with #[serde(skip_deserializing)]",
                        variant.ident, ident
                    ));
                }
            }
        }
    }
}

/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(
    cx: &Ctxt,
    cont: &Container,
) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => return,
    };

    let tag = match *cont.attrs.tag() {
        EnumTag::Internal { ref tag } => tag.as_str(),
        EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
    };

    let diagnose_conflict = || {
        let message = format!(
            "variant field name `{}` conflicts with internal tag",
            tag
        );
        cx.error(message);
    };

    for variant in variants {
        match variant.style {
            Style::Struct => {
                for field in &variant.fields {
                    let check_ser = !field.attrs.skip_serializing();
                    let check_de = !field.attrs.skip_deserializing();
                    let name = field.attrs.name();
                    let ser_name = name.serialize_name();
                    let de_name = name.deserialize_name();

                    if check_ser && ser_name == tag || check_de && de_name == tag {
                        diagnose_conflict();
                        return;
                    }
                }
            },
            Style::Unit | Style::Newtype | Style::Tuple => {},
        }
    }
}
<commit_msg>add a check for conflicting adjacent tags as well<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::{Data, Container, Style};
use attr::{Identifier, EnumTag};
use Ctxt;

/// Cross-cutting checks that require looking at more than a single attrs
/// object. Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &Container) {
    check_getter(cx, cont);
    check_identifier(cx, cont);
    check_variant_skip_attrs(cx, cont);
    check_internal_tag_field_name_conflict(cx, cont);
    check_adjacent_tag_conflict(cx, cont);
}

/// Getters are only allowed inside structs (not enums) with the `remote`
/// attribute.
fn check_getter(cx: &Ctxt, cont: &Container) {
    match cont.data {
        Data::Enum(_) => {
            if cont.data.has_getter() {
                cx.error("#[serde(getter = \"...\")] is not allowed in an enum");
            }
        }
        Data::Struct(_, _) => {
            if cont.data.has_getter() && cont.attrs.remote().is_none() {
                cx.error(
                    "#[serde(getter = \"...\")] can only be used in structs \
                     that have #[serde(remote = \"...\")]",
                );
            }
        }
    }
}

/// The `other` attribute must be used at most once and it must be the last
/// variant of an enum that has the `field_identifier` attribute.
///
/// Inside a `variant_identifier` all variants must be unit variants. Inside a
/// `field_identifier` all but possibly one variant must be unit variants. The
/// last variant may be a newtype variant which is an implicit "other" case.
fn check_identifier(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for (i, variant) in variants.iter().enumerate() {
        match (
            variant.style,
            cont.attrs.identifier(),
            variant.attrs.other(),
        ) {
            // The `other` attribute may only be used in a field_identifier.
            (_, Identifier::Variant, true) | (_, Identifier::No, true) => {
                cx.error("#[serde(other)] may only be used inside a field_identifier");
            }

            // Variant with `other` attribute must be the last one.
            (Style::Unit, Identifier::Field, true) => {
                if i < variants.len() - 1 {
                    cx.error("#[serde(other)] must be the last variant");
                }
            }

            // Variant with `other` attribute must be a unit variant.
            (_, Identifier::Field, true) => {
                cx.error("#[serde(other)] must be on a unit variant");
            }

            // Any sort of variant is allowed if this is not an identifier.
            (_, Identifier::No, false) => {}

            // Unit variant without `other` attribute is always fine.
            (Style::Unit, _, false) => {}

            // The last field is allowed to be a newtype catch-all.
            (Style::Newtype, Identifier::Field, false) => {
                if i < variants.len() - 1 {
                    cx.error(format!("`{}` must be the last variant", variant.ident));
                }
            }

            (_, Identifier::Field, false) => {
                cx.error("field_identifier may only contain unit variants");
            }

            (_, Identifier::Variant, false) => {
                cx.error("variant_identifier may only contain unit variants");
            }
        }
    }
}

/// Skip-(de)serializing attributes are not allowed on variants marked
/// (de)serialize_with.
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => {
            return;
        }
    };

    for variant in variants.iter() {
        if variant.attrs.serialize_with().is_some() {
            if variant.attrs.skip_serializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(serialize_with)] and \
                     #[serde(skip_serializing)]",
                    variant.ident
                ));
            }

            for (i, field) in variant.fields.iter().enumerate() {
                let ident = field
                    .ident
                    .as_ref()
                    .map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));

                if field.attrs.skip_serializing() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing)]",
                        variant.ident, ident
                    ));
                }

                if field.attrs.skip_serializing_if().is_some() {
                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(serialize_with)] and \
                         a field {} marked with #[serde(skip_serializing_if)]",
                        variant.ident, ident
                    ));
                }
            }
        }

        if variant.attrs.deserialize_with().is_some() {
            if variant.attrs.skip_deserializing() {
                cx.error(format!(
                    "variant `{}` cannot have both #[serde(deserialize_with)] and \
                     #[serde(skip_deserializing)]",
                    variant.ident
                ));
            }

            for (i, field) in variant.fields.iter().enumerate() {
                if field.attrs.skip_deserializing() {
                    let ident = field
                        .ident
                        .as_ref()
                        .map_or_else(|| format!("{}", i), |ident| format!("`{}`", ident));

                    cx.error(format!(
                        "variant `{}` cannot have both #[serde(deserialize_with)] \
                         and a field {} marked with #[serde(skip_deserializing)]",
                        variant.ident, ident
                    ));
                }
            }
        }
    }
}

/// The tag of an internally-tagged struct variant must not be
/// the same as either one of its fields, as this would result in
/// duplicate keys in the serialized output and/or ambiguity in
/// the to-be-deserialized input.
fn check_internal_tag_field_name_conflict(
    cx: &Ctxt,
    cont: &Container,
) {
    let variants = match cont.data {
        Data::Enum(ref variants) => variants,
        Data::Struct(_, _) => return,
    };

    let tag = match *cont.attrs.tag() {
        EnumTag::Internal { ref tag } => tag.as_str(),
        EnumTag::External | EnumTag::Adjacent { .. } | EnumTag::None => return,
    };

    let diagnose_conflict = || {
        let message = format!(
            "variant field name `{}` conflicts with internal tag",
            tag
        );
        cx.error(message);
    };

    for variant in variants {
        match variant.style {
            Style::Struct => {
                for field in &variant.fields {
                    let check_ser = !field.attrs.skip_serializing();
                    let check_de = !field.attrs.skip_deserializing();
                    let name = field.attrs.name();
                    let ser_name = name.serialize_name();
                    let de_name = name.deserialize_name();

                    if check_ser && ser_name == tag || check_de && de_name == tag {
                        diagnose_conflict();
                        return;
                    }
                }
            },
            Style::Unit | Style::Newtype | Style::Tuple => {},
        }
    }
}

/// In the case of adjacently-tagged enums, the type and the
/// contents tag must differ, for the same reason.
fn check_adjacent_tag_conflict(cx: &Ctxt, cont: &Container) {
    let (type_tag, content_tag) = match *cont.attrs.tag() {
        EnumTag::Adjacent { ref tag, ref content } => (tag, content),
        EnumTag::Internal { .. } | EnumTag::External | EnumTag::None => return,
    };

    if type_tag == content_tag {
        let message = format!(
            "Enum tags `{}` for type and content conflict with each other",
            type_tag
        );
        cx.error(message);
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/solving-questions-with-brainpower/
pub fn most_points(questions: Vec<Vec<i32>>) -> i64 {
    todo!()
}

fn main() {
    println!(
        "{}",
        most_points(vec![vec![3, 2], vec![4, 3], vec![4, 4], vec![2, 5]])
    ); // 5
    println!(
        "{}",
        most_points(vec![
            vec![1, 1],
            vec![2, 2],
            vec![3, 3],
            vec![4, 4],
            vec![5, 5]
        ])
    ); // 7
}
<commit_msg>Solve problem 2140<commit_after>use std::cmp;

// https://leetcode.com/problems/solving-questions-with-brainpower/
pub fn most_points(questions: Vec<Vec<i32>>) -> i64 {
    fn f(questions: &Vec<Vec<i32>>, index: i32, memo: &mut Vec<i64>) -> i64 {
        if (index as usize) >= questions.len() {
            return 0;
        }
        if memo[index as usize] != -1 {
            return memo[index as usize];
        }
        let points = &questions[index as usize][0];
        let brainpower = &questions[index as usize][1];
        let solve = f(questions, index + brainpower + 1, memo) + *points as i64;
        let skip = f(questions, index + 1, memo);
        let max: i64 = cmp::max(solve, skip);
        memo[index as usize] = max;
        max
    }
    f(&questions, 0, &mut vec![-1; questions.len() as usize])
}

fn main() {
    println!(
        "{}",
        most_points(vec![vec![3, 2], vec![4, 3], vec![4, 4], vec![2, 5]])
    ); // 5
    println!(
        "{}",
        most_points(vec![
            vec![1, 1],
            vec![2, 2],
            vec![3, 3],
            vec![4, 4],
            vec![5, 5]
        ])
    ); // 7
}
<|endoftext|>


<commit_before>use std::env;
use std::net::TcpStream;
use std::io::prelude::*;
use std::fs::File;

fn main() {
    println!("Start Download Manager");

    //let tab: Vec<_> = env::args().collect();
    //assert_ne!(tab.len(), 1);
    let mut file = File::create("received_file").unwrap();
    let mut stream = TcpStream::connect("127.0.0.1:8080").unwrap();
    println!("Connected to the host");
    let mut buf = vec![] ;
    println!("Start downloading the file");
    loop {
        match stream.read(&mut buf) {
            Ok(n)=> {
                if n == 0 {
                    println!("No data");
                    break;
                }
            },
            Err(error) => println!("{}", error.to_string()),
        }
    }
    println!("Write the downloaded file into the disk");
    file.write_all(&mut buf).unwrap();
}
<commit_msg>use of UDP instead<commit_after>use std::env;
use std::io::prelude::*;
use std::net::UdpSocket;
use std::fs::File;

fn main() {
    println!("Start Download Manager");

    //let tab: Vec<_> = env::args().collect();
    //assert_ne!(tab.len(), 1);
    let mut file = File::create("received_file").unwrap();
    let stream = UdpSocket::bind("127.0.0.1:8080").expect("could not bind to address");
    println!("Connected to the host");
    let mut buf = vec![] ;
    println!("Start downloading the file");
    let result = stream.recv_from(&mut buf);
    drop(stream);

    match result {
        Ok ((size, src)) => {
            println!("Received data from {}", src);
            println!("Size received = {}", size);
        },
        Err(error) => println!("{}", error.to_string()),
    }
    println!("Write the downloaded file into the disk");
    file.write_all(&mut buf).unwrap();
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use anyhow::Result;

use crate::{
    not_bash::{fs2, pushd, pwd, rm_rf, run},
    project_root,
};

pub fn run_dist(nightly: bool) -> Result<()> {
    let dist = project_root().join("dist");
    rm_rf(&dist)?;
    fs2::create_dir_all(&dist)?;

    if cfg!(target_os = "linux") {
        dist_client(nightly)?;
    }
    dist_server()?;
    Ok(())
}

fn dist_client(nightly: bool) -> Result<()> {
    let _d = pushd("./editors/code");

    let package_json_path = pwd().join("package.json");
    let original_package_json = fs2::read_to_string(&package_json_path)?;
    let _restore =
        Restore { path: package_json_path.clone(), contents: original_package_json.clone() };

    let mut package_json = original_package_json.replace(r#""enableProposedApi": true,"#, r#""#);

    if nightly {
        package_json = package_json.replace(
            r#""displayName": "rust-analyzer""#,
            r#""displayName": "rust-analyzer nightly""#,
        );
    } else {
        package_json = original_package_json.replace(r#""enableProposedApi": true,"#, r#""#);
    }
    fs2::write(package_json_path, package_json)?;

    run!("npx vsce package -o ../../dist/rust-analyzer.vsix")?;
    Ok(())
}

fn dist_server() -> Result<()> {
    if cfg!(target_os = "linux") {
        std::env::set_var("CC", "clang");
        run!("cargo build --package rust-analyzer --bin rust-analyzer --release --target x86_64-unknown-linux-musl")?;
        run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?;
    } else {
        run!("cargo build --package rust-analyzer --bin rust-analyzer --release")?;
    }

    let (src, dst) = if cfg!(target_os = "linux") {
        ("./target/x86_64-unknown-linux-musl/release/rust-analyzer", "./dist/rust-analyzer-linux")
    } else if cfg!(target_os = "windows") {
        ("/target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
    } else if cfg!(target_os = "macos") {
        ("/target/release/rust-analyzer", "./dist/rust-analyzer-mac")
    } else {
        panic!("Unsupported OS")
    };

    fs2::copy(src, dst)?;

    Ok(())
}

struct Restore {
    path: PathBuf,
    contents: String,
}

impl Drop for Restore {
    fn drop(&mut self) {
        fs2::write(&self.path, &self.contents).unwrap();
    }
}
<commit_msg>Fix dist again<commit_after>use std::path::PathBuf;

use anyhow::Result;

use crate::{
    not_bash::{fs2, pushd, pwd, rm_rf, run},
    project_root,
};

pub fn run_dist(nightly: bool) -> Result<()> {
    let dist = project_root().join("dist");
    rm_rf(&dist)?;
    fs2::create_dir_all(&dist)?;

    if cfg!(target_os = "linux") {
        dist_client(nightly)?;
    }
    dist_server()?;
    Ok(())
}

fn dist_client(nightly: bool) -> Result<()> {
    let _d = pushd("./editors/code");

    let package_json_path = pwd().join("package.json");
    let original_package_json = fs2::read_to_string(&package_json_path)?;
    let _restore =
        Restore { path: package_json_path.clone(), contents: original_package_json.clone() };

    let mut package_json = original_package_json.replace(r#""enableProposedApi": true,"#, r#""#);

    if nightly {
        package_json = package_json.replace(
            r#""displayName": "rust-analyzer""#,
            r#""displayName": "rust-analyzer nightly""#,
        );
    } else {
        package_json = original_package_json.replace(r#""enableProposedApi": true,"#, r#""#);
    }
    fs2::write(package_json_path, package_json)?;

    run!("npx vsce package -o ../../dist/rust-analyzer.vsix")?;
    Ok(())
}

fn dist_server() -> Result<()> {
    if cfg!(target_os = "linux") {
        std::env::set_var("CC", "clang");
        run!("cargo build --package rust-analyzer --bin rust-analyzer --release --target x86_64-unknown-linux-musl")?;
        run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?;
    } else {
        run!("cargo build --package rust-analyzer --bin rust-analyzer --release")?;
    }

    let (src, dst) = if cfg!(target_os = "linux") {
        ("./target/x86_64-unknown-linux-musl/release/rust-analyzer", "./dist/rust-analyzer-linux")
    } else if cfg!(target_os = "windows") {
        ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
    } else if cfg!(target_os = "macos") {
        ("./target/release/rust-analyzer", "./dist/rust-analyzer-mac")
    } else {
        panic!("Unsupported OS")
    };

    fs2::copy(src, dst)?;

    Ok(())
}

struct Restore {
    path: PathBuf,
    contents: String,
}

impl Drop for Restore {
    fn drop(&mut self) {
        fs2::write(&self.path, &self.contents).unwrap();
    }
}
<|endoftext|>