My family and I had fun playing Mancala together and I really liked the simplicity of its rules but have a few questions such as "What is the highest possible score". I thought it would be a fun little project to implement in Rust but I am stuck and need help.
There are many rules of how to play Mancala. I want to implement this version: https://www.youtube.com/watch?v=-A-djjimCcM. Knowing the rules of the game makes understanding my problem easier, but it probably isn't required to get it.
This is how a Mancala board looks like:
| |04|04|04|04|04|04| |
|00|-----------------|00|
| |04|04|04|04|04|04| |
Each of the numbers represent a hole. The numbers on the left and right in the bigger boxes represent a "mancala". A mancala is basically a hole where you count your points. The one on your right, is your own mancala, the one on the left is your opponent's mancala. The numbers represent the number of marbles in that specific hole.
In the game, you can select a hole, take all its marbles and then drop one marble in each of the next holes/mancala until you run out of marbles. You skip your opponent's mancala. This is what I am struggling with.
This is how I tried to solve it:
The Mancala board is a struct that has four arrays storing Holes. One for each of the holes on the side of the player and one for their mancala. I want to chain together and cycle through three of these arrays of Holes so I can run an associated function on those Holes (the opponent's mancala gets skipped). This is my code:
pub const STARTING_MARBLES: i8 = 4;
pub const NO_OF_HOLES_OF_EACH_PLAYER: usize = 6;
// There can be two players
#[derive(Debug, Copy, Clone)]
pub enum Player {
A,
B,
}
// A dip in a mancala board that can contain a number of marbles
#[derive(Debug, Copy, Clone)]
struct Hole {
marbles: i8,
}
impl Hole {
// Adds x marbles to the hole
fn add_x(&mut self, x: i8) {
self.marbles += x;
}
// Takes all marbles from the hole and returns their number
fn take_all(&mut self) -> i8 {
let marbles = self.marbles;
self.marbles = 0;
marbles
}
// Returns the number of marbles in the hole
fn count(&self) -> i8 {
self.marbles
}
}
// A mancala board with all its holes and mancalas to count the players points
#[derive(Debug, Copy, Clone)]
pub struct Board {
holes_a: [Hole; NO_OF_HOLES_OF_EACH_PLAYER],
holes_b: [Hole; NO_OF_HOLES_OF_EACH_PLAYER],
mancala_a: [Hole; 1],
mancala_b: [Hole; 1],
}
impl Board {
// Create, initialize and return a new mancala board
pub fn new() -> Self {
let init_hole = Hole {
marbles: STARTING_MARBLES,
};
let holes_a = [init_hole; NO_OF_HOLES_OF_EACH_PLAYER];
let holes_b = [init_hole; NO_OF_HOLES_OF_EACH_PLAYER];
let mancala_a = [Hole { marbles: 0 }];
let mancala_b = [Hole { marbles: 0 }];
Board {
holes_a,
holes_b,
mancala_a,
mancala_b,
}
}
// Take all marbles from the chosen hole and add them to the following holes and the player's mancala
// player: Player whos turn it is
// no: number of the selected hole. The numbering starts with 0 on the very left hole of the player whos turn it is
pub fn choose_hole(mut self, player: Player, no: usize) {
let (mut players_own_holes, other_players_holes, players_mancala) = match player {
Player::A => (self.holes_a, self.holes_b, self.mancala_a),
Player::B => (self.holes_b, self.holes_a, self.mancala_b),
};
let marbles_to_spend = players_own_holes[no].take_all() as usize;
let holes_iter = self
.holes_a
.iter_mut()
.chain(self.mancala_a.iter_mut())
.chain(self.holes_b.iter_mut())
.cycle()
.skip(no + 1)
.take(marbles_to_spend);
for mut hole in holes_iter {
hole.add_x(1);
}
}
}
However I get the following error:
error[E0277]: the trait bound `std::slice::IterMut<'_, Hole>: Clone` is not satisfied
--> src/lib.rs:75:14
|
75 | .cycle()
| ^^^^^ the trait `Clone` is not implemented for `std::slice::IterMut<'_, Hole>`
|
= note: required because of the requirements on the impl of `Clone` for `std::iter::Chain<std::iter::Chain<std::slice::IterMut<'_, Hole>, std::slice::IterMut<'_, Hole>>, std::slice::IterMut<'_, Hole>>`
note: required by a bound in `cycle`
--> /home/batman/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:3262:23
|
3262 | Self: Sized + Clone,
| ^^^^^ required by this bound in `cycle`
I also tried using the into_iter() method instead. I didn't get any errors then but the values of the holes did not change. I guess a copy was created and the method ran on the copy and then the copy went out of scope and it looked like nothing was changed.
The cycle() iterator method works internally by cloning the input iterator, iterating the clone until it returns None, and then replacing the clone with another clone of the input iterator. This requires that the input iterator can be cloned, but an iterator of mutable references to slice elements can't be cloned, because then you'd be able to call next() on the original and the clone and have two mutable references to the same value. This is supposed to be impossible in Rust, so std::slice::IterMut can't be cloned, and therefore you can't use .cycle() on it.
One way to solve this problem would be to alter your data structure. Arrays of one element generally indicate a design problem; you can accomplish the same thing with just a single value, anyway.
To make this problem simpler, just use a single array, with circular indices. Something like this:
| |12|11|10|09|08|07| |
|13|-----------------|06|
| |00|01|02|03|04|05| |
So now your data structure is simply struct Board { holes: [Hole; 14] }.
Traversing this data structure now becomes incredibly simple -- you can just do (0..14).cycle() to get a repeating iterator of array indices.
When using this data structure, we need to handle the game rule of skipping your opponent's mancala as marbles are distributed. We can handle this, along with handling which side of the board to start on, with a simple match, skip, and filter:
let (opponent_mancala_index, start_idx) = match player {
Player::A => (13, 0),
Player::B => (6, 7),
};
let indexes = (0..14)
.cycle()
.skip(no + start_idx)
.filter(|&v| v != opponent_mancala_index)
.take(marbles_to_spend);
for i in indexes {
self.holes[i].add_x(1);
}
You might consider making these special indexes named constants.
Also, note that your Board::choose_hole() function should take &mut self instead of mut self, otherwise you are making changes to a copy and then discarding that copy.
Related
I am working on a little parser that takes an S-Expression and transforms it into a tree data structure. Since trees are not so easy in Rust to do bidirectional I want to make it only one-directional (each node only knows it's children, not it's parents). To still be able to access nodes that have been created in the past, I want to store all nodes in a Vector and keep an index that tells me which node is where. E.g. a node would have a field parent_index, with the index of it's parent node in the vector, without needing to have a direct reference to it.
So, while I iterate over the String that is my s-expression, I am creating new nodes and want to push them into the vector, as well as assigning child relationships.
for clarifications an S-Expression can be this (w1 (w2 t1) (w3 t2)) or something like this (S (F (FIRSTWORD This) (SECONDWORD is)) (Z (THIRDWORD a) (FOURTHWORD sentence))), or just a terminal like Hello
A lot is still missing but my idea looks like this. My question now is: How can I create all these Trees inside the loop and store them into the vector outside of the loop?
It seems that the borrow checker has some probelems with this...
I am very grateful for any help! Thank you :)
My idea looks like this:
pub struct Tree{
pub root: String,
pub children: Vec<Tree>
}
fn parse_to_tree(mut s_expr: String) -> Tree{
// Vector for all nodes
let mut all_nodes:Vec<&Tree> = Vec::new();
// Index of node we are working on
let mut curr_node_index = 0;
while !s_expr.is_empty(){
// get first char from s expression
let mut c_c = s_expr.remove(0);
//Names: c_c: current_char, c_w: current:word
// only continue if we start with '(', otherwise Leaf
while c_c == '('{
let mut c_w = String::from("");
while c_c != ' '{
c_c = s_expr.remove(0);
c_w.push(c_c);
}
println!("{}", c_w);
let node = Tree{root: c_w, children: Vec::new()};
//Here I want to push the node by reference to the all_nodes_vector
all_nodes.push(&node); // HERE occurs the error: borrowed value does not live long enough...
if !all_nodes.is_empty(){
// Here I want to to push the new node as a child to the old current_node
all_nodes[curr_node_index].children.push(node);
}
curr_node_index += 1;
}
return Tree{root: s_expr, children: Vec::new()};
}
return Tree{root: s_expr, children: Vec::new()};
}
You cannot do that (safely): someone, somewhere, while building this tree, will have to hold both a node and the list of nodes that contains this node. And (at least) the reference to the node will be mutable (because we need to build it), causing a violation of the borrow rules.
The solution is simple: just give up on using references. Store all nodes in a vector, and only keep indices to this vector. This is easy, effective and idiomatic.
I have an iterator in Rust that loops over a Vec<u8> and applies the same function at two different stages. I do this by chaining a couple of map functions together. Here is the relevant code (where example, example_function_1, and example_function_2 are stand-in variables and functions respectively):
NOTE: example.chunks() is a custom function! Not the default one on slices!
let example = vec![0, 1, 2, 3];
let mut hashers = Cycler::new([example_function_1, example_function_2].iter());
let ret: Vec<u8> = example
//...
.chunks(hashers.len())
.map(|buf| hashers.call(buf))
//...
.map(|chunk| hashers.call(chunk))
.collect();
Here is the code for Cycler:
pub struct Cycler<I> {
orig: I,
iter: I,
len: usize,
}
impl<I> Cycler<I>
where
I: Clone + Iterator,
I::Item: Fn(Vec<u8>) -> Vec<u8>,
{
pub fn new(iter: I) -> Self {
Self {
orig: iter.clone(),
len: iter.clone().count(),
iter,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn reset(&mut self) {
self.iter = self.orig.clone();
}
pub fn call(&mut self, buf: Bytes) -> Bytes {
// It is safe to unwrap because it should indefinietly continue without stopping
self.next().unwrap()(buf)
}
}
impl<I> Iterator for Cycler<I>
where
I: Clone + Iterator,
I::Item: Fn(Vec<u8>) -> Vec<u8>,
{
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
match self.iter.next() {
next => next,
None => {
self.reset();
self.iter.next()
}
}
}
// No size_hint, try_fold, or fold methods
}
What confuses me is that the second time I reference hashers it says this:
error[E0499]: cannot borrow `hashers` as mutable more than once at a time
--> libpressurize/src/password/password.rs:28:14
|
21 | .map(|buf| hashers.call(buf))
| ----- ------- first borrow occurs due to use of `hashers` in closure
| |
| first mutable borrow occurs here
...
28 | .map(|chunk| hashers.call(chunk))
| --- ^^^^^^^ ------- second borrow occurs due to use of `hashers` in closure
| | |
| | second mutable borrow occurs here
| first borrow later used by call
Shouldn't this work because the mutable reference is not used at the same time?
Please let me know if more info/code is needed to answer this.
.map(|buf| hashers.call(buf))
You're probably thinking that in the above line, hashers is mutably borrowed to call it. That's true (since Cycler::call takes &mut self) but it's not what the compiler error is about. In this line, hashers is mutably borrowed to construct the closure |buf| hashers.call(buf), and that borrow lasts as long as the closure does.
Thus, when you write
.map(|buf| hashers.call(buf))
//...
.map(|chunk| hashers.call(chunk))
you are constructing two closures which live at the same time (assuming this is std::iter::Iterator::map) and mutably borrowing hashers for each of them, which is not allowed.
This error is actually protecting you against a side-effect hazard: it's not obvious (in a purely local analysis) what order the side effects of the two call()s will be performed in, because the map()s could do anything they like with the closures. Given the code you wrote, I assume you're doing this on purpose, but the compiler doesn't know that you know what you're doing.
(We can't even predict what the interleaving will be just because they're iterators. Inside of your //... there could be, say a .filter() step which leads to hashers.call(buf) being called several times between each call to hashers.call(chunk), or something else that produces a different number of outputs than inputs.)
If you know that you want the interleaving of side-effects that is “whenever either map() decides to call it”, then you can gain that freedom with a RefCell or other interior mutability, as dianhenglau's answer demonstrates.
Shouldn't this work because the mutable reference is not used at the same time?
No. The rules of references stated that "At any given time, you can have either one mutable reference or any number of immutable references", no matter if it is or isn't used at the same time. See this answer for the reason behind the rules.
As for workaround, since you're sure that the mutations do not occur simultaneously, you can use std::cell::RefCell as explained in this chapter. Modify the code into:
use std::cell::RefCell;
let example = vec![0, 1, 2, 3];
// Remove the "mut", wrap Cycler in RefCell.
let hashers = RefCell::new(Cycler::new([example_function_1, example_function_2].iter()));
let ret: Vec<u8> = example
//...
.chunks(hashers.borrow().len())
// Borrow hashers as immutable inside the closure, then borrow the Cycler as mutable.
.map(|buf| hashers.borrow_mut().call(buf))
//...
.map(|chunk| hashers.borrow_mut().call(chunk))
.collect();
I'm trying to implement a commonly used pattern - using the result of a previous loop iteration in the next loop iteration. For example, to implement pagination where you need to give the id of the last value on the previous page.
struct Result {
str: String,
}
fn main() {
let times = 10;
let mut last: Option<&str> = None;
for i in 0..times {
let current = do_something(last);
last = match current {
Some(r) => Some(&r.str.to_owned()),
None => None,
};
}
}
fn do_something(o: Option<&str>) -> Option<Result> {
Some(Result {
str: "whatever string".to_string(),
})
}
However, I'm not sure how to actually get the value out of the loop. Currently, the compiler error is temporary value dropped while borrowed (at &r.str.to_owned()), though I made many other attempts, but to no avail.
The only way I found to actually get it working is to create some sort of local tmp_str variable and do a hack like this:
match current {
Some(r) => {
tmp_str.clone_from(&r.str);
last = Some(&tmp_str);
}
None => {
last = None;
}
}
But that doesn't feel like it's the way it's supposed to be done.
In your code, it remains unclear who the owner of the String referenced in last: Option<&str> is supposed to be. You could introduce an extra mutable local variable that owns the string. But then you would have two variables: the owner and the reference, which seems redundant. It would be much simpler to just make last the owner:
struct MyRes {
str: String,
}
fn main() {
let times = 10;
let mut last: Option<String> = None;
for _i in 0..times {
last = do_something(&last).map(|r| r.str);
}
}
fn do_something(_o: &Option<String>) -> Option<MyRes> {
Some(MyRes {
str: "whatever string".to_string(),
})
}
In do_something, you can just pass the whole argument by reference, this seems more likely to be what you wanted. Also note that naming your own struct Result is a bad idea, because Result is such a pervasive trait built deeply into the compiler (?-operator etc).
Follow-up question: Option<&str> or Option<String>?
Both Option<&str> and Option<String> have different trade-offs. One is better for passing string literals, other is better for passing owned Strings. I'd actually propose to use neither, and instead make the function generic over type S that implements AsRef<str>. Here is a comparison of various methods:
fn do_something(o: &Option<String>) {
let _a: Option<&str> = o.as_ref().map(|r| &**r);
let _b: Option<String> = o.clone();
}
fn do_something2(o: &Option<&str>) {
let _a: Option<&str> = o.clone(); // do you need it?
let _b: Option<String> = o.map(|r| r.to_string());
}
fn do_something3<S: AsRef<str>>(o: &Option<S>) {
let _a: Option<&str> = o.as_ref().map(|s| s.as_ref());
let _b: Option<String> = o.as_ref().map(|r| r.as_ref().to_string());
}
fn main() {
let x: Option<String> = None;
let y: Option<&str> = None;
do_something(&x); // nice
do_something(&y.map(|r| r.to_string())); // awkward & expensive
do_something2(&x.as_ref().map(|x| &**x)); // cheap but awkward
do_something2(&y); // nice
do_something3(&x); // nice
do_something3(&y); // nice, in both cases
}
Note that not all of the above combinations are very idiomatic, some are added just for completeness (e.g. asking for AsRef<str> and then building an owned String out of seems a bit strange).
r.str.to_owned() is a temporary value. You can take a reference to a temporary, but because the temporary value will usually be dropped (destroyed) at the end of the innermost enclosing statement, the reference becomes dangling at that point. In this case the "innermost enclosing statement" is either the last line of the loop, or the loop body itself -- I'm not sure exactly which one applies here, but it doesn't matter, because either way, you're trying to make last contain a reference to a String that will soon be dropped, making last unusable. The compiler is right to stop you from using it again in the next iteration of the loop.
The easiest fix is just to not make last a reference at all -- in the example, it's not necessary or desirable. Just use Option<String>:
fn main() {
let times = 10;
let mut last = None;
for _ in 0..times {
last = match do_something(last) {
Some(r) => Some(r.str),
None => None,
};
}
}
fn do_something(_: Option<String>) -> Option<Result> {
// ...
}
There are also ways to make the reference version work; here is one:
let mut current; // lift this declaration out of the loop so `current` will have
// a lifetime longer than one iteration
for _ in 0..times {
current = do_something(last);
last = match current {
Some(ref r) => Some(&r.str), // borrow from `current` in the loop instead
// of from a newly created String
None => None,
};
}
You might want to do this if your code is more complicated than the example and using String would mean a lot of potentially expensive .clone()s.
I have a fixed size array of Strings: [String; 2]. I want to turn it into a (String, String). Can I do this without copying the values?
The piece of code that I'm working on in particular is the following:
let (basis, names_0, names_1) = if let Some(names) = self.arg_name {
(ComparisonBasis::Name, names[0], names[1])
} else {
(ComparisonBasis::File, self.arg_file[0], self.arg_file[1])
};
types:
self.arg_name: Option<[String; 2]>
self.arg_file: Vec<String>
Right now I'm getting errors
cannot move out of type `[std::string::String; 2]`, a non-copy fixed-size array [E0508]
and
cannot move out of indexed content [E0507]
for the two arms of the if
You've omitted a fair amount of context, so I'm taking a guess at a few aspects. I'm also hewing a little closer to the question you asked, rather than the vaguer one implied by your snippets.
struct NeverSpecified {
arg_names: Option<[String; 2]>,
arg_file: Vec<String>,
}
impl NeverSpecified {
fn some_method_i_guess(mut self) -> (String, String) {
if let Some(mut names) = self.arg_names {
use std::mem::replace;
let name_0 = replace(&mut names[0], String::new());
let name_1 = replace(&mut names[1], String::new());
(name_0, name_1)
} else {
let mut names = self.arg_file.drain(0..2);
let name_0 = names.next().expect("expected 2 names, got 0");
let name_1 = names.next().expect("expected 2 names, got 1");
(name_0, name_1)
}
}
}
I use std::mem::replace to switch the contents of the array, whilst leaving it in a valid state. This is necessary because Rust won't allow you to have a "partially valid" array. There are no copies or allocations involved in this path.
In the other path, we have to pull elements out of the vector by hand. Again, you can't just move values out of a container via indexing (this is actually a limitation of indexing overall). Instead, I use Vec::drain to essentially chop the first two elements out of the vector, then extract them from the resulting iterator. To be clear: this path doesn't involve any copies or allocations, either.
As an aside, those expect methods shouldn't ever be triggered (since drain does bounds checking), but better paranoid than sorry; if you want to replace them with unwrap() calls instead, that should be fine..
Since Rust 1.36, you can use slice patterns to bind to all the values of the array at once:
struct NeverSpecified {
arg_names: Option<[String; 2]>,
arg_file: Vec<String>,
}
impl NeverSpecified {
fn some_method_i_guess(mut self) -> (String, String) {
if let Some([name_0, name_1]) = self.arg_names.take() {
(name_0, name_1)
} else {
let mut names = self.arg_file.drain(0..2);
let name_0 = names.next().expect("expected 2 names, got 0");
let name_1 = names.next().expect("expected 2 names, got 1");
(name_0, name_1)
}
}
}
See also:
Method for safely moving all elements out of a generic array into a tuple with minimal overhead
NOTE: See amended post below re: Hardware mirroring
I have written two Swift functions that toggle the display mirroring in OSX. Both work; the difference between them is just syntax when dealing with pointers. For the convenience of those interested in learning how to toggle mirroring in Swift, I have included the text of the playground file below.
My question is about memory allocation. Here is the section of interest:
toggleMirroringUgly
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
toggleMirroring
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
CGGetActiveDisplayList is a low-level function call that relies on data being arranged in consecutive memory locations. I am reasonably confident that “alloc” from the ugly version is contiguous. Empirically, it seems that the “Array(…)” call is also contiguous, but can I rely on that always being true (e.g., if the number of displays grows)? Is this assumption about the Swift array initializer poor form?
Here’s all the code; apologies for formatting issues. Note that only one of the two functions should be called; otherwise, you’ll end up where you started.
//: Playground - noun: a place where people can play
import Cocoa
// apparently not defined in Swift version of SDK 10.11 (XCode 7.3.1), so add manually
let kCGNullDirectDisplay = CGDirectDisplayID(0)
let kCGDirectMainDisplay = CGMainDisplayID() // not used here, just for the record
let maxDisplays:UInt32 = 20 // not used
var onlineCount:UInt32 = 0 // not used
func postError(error : CGError){
if error != CGError.Success {
print("got an error")
}
}
// this toggles all active displays, online or not
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
//***
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
//***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef = nil //swift 3 syntax
postError(CGBeginDisplayConfiguration(&configRef));
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master);
}
}
if (false){ // change to true in order to execute the toggle
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.Permanently))
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
func toggleMirroringUgly(){
// just to decrease eye strain
typealias displayIDListPtr = UnsafeMutablePointer<CGDirectDisplayID>
typealias configurationRefPtr = UnsafeMutablePointer<CGDisplayConfigRef>
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
// ***
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
// ***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// make room for the configuration reference
let configRefPtr = configurationRefPtr.alloc(1) //see typealias above
// start the configuration
postError(CGBeginDisplayConfiguration (configRefPtr));
for i in 0..<displayCount {
let currentDisplay = CGDirectDisplayID(displayListPtr[Int(i)])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRefPtr[0], currentDisplay, master);
}
}
if (false){ //change to true in order to flip the mirroring
// make it happen
postError(CGCompleteDisplayConfiguration (configRefPtr[0],CGConfigureOption.Permanently));
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
toggleMirroring()
Arrays don't necessarily use contiguous storage. There is a ContiguousArray type which you can use if you are so inclined, but you'll still need to deal with the possible difference between your maximum size and the actual size returned after the final call to CGGetActiveDisplayList.
One way of cleaning this up might be to make a custom convenience initializer for Array:
extension Array {
init<Size: IntegerType>(
fillingBufferOfSize maxSize: Size,
#noescape fillBuffer: (buffer: UnsafeMutablePointer<Element>, count: inout Size) throws -> ()) rethrows
{
let maxSizeAsInt = Int(maxSize.toIntMax())
let buf = UnsafeMutablePointer<Element>.alloc(maxSizeAsInt)
defer { buf.dealloc(maxSizeAsInt) }
var actualCount: Size = 0
try fillBuffer(buffer: buf, count: &actualCount)
self.init(UnsafeBufferPointer(start: buf, count: Int(actualCount.toIntMax())))
}
}
Then you can use Array(fillingBufferOfSize: ...):
var maxActive: UInt32 = 0
CGGetActiveDisplayList(0, nil, &maxActive)
let displays = Array(fillingBufferOfSize: maxActive) { (buffer, count) in
CGGetActiveDisplayList(maxActive, buffer, &count)
}
I upgraded my computer with a new video card and NVIDIA drivers and discovered my code above no longer works fully - turns mirroring on but not off. Apparently, there's an option for drivers to use hardware or software mirroring, and that changes the coding. I post below a revised version.
It has only been tested on my system (10.12.2) and card (GTX 980Ti), but I think the logic should accommodate software mirroring and fairly recent OS versions as well. If you have more than 2 displays, you can probably modify it, with heroic effort, to mirror arbitrary combinations. My code will just mirror whatever is considered the main display (or the lowest rez one, in software mirroring) on all the others.
Although jbandes' note re: ContiguousArray was informative, it does not work in this case - see the comments in the code. This code assumes that the allocated array of UInt32s will be contiguous. (Too much work to get fancy with malloc and casting, but this is not production ready.)
Good luck to the 2 people who might be interested!
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
func postError(_ error : CGError){
if error != CGError.success {
print("got an error")
}
}
func disableHardwareMirroring(){
// designed for hardware mirroring with > 1 display
// should be no penalty for running with only 1 display, using either hardware or software mirroring drivers
// but not tested
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
// only interested in the main display
// kCGNullDirectDisplay parameter disables hardware mirroring
CGConfigureDisplayMirrorOfDisplay(configRef, CGMainDisplayID(), kCGNullDirectDisplay)
// may not be permanent between boots using Playgroud, but is in an application
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
}
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0 //used as a parameter, but value is ignored
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount == 1 {
// either it's hardware mirroring or who cares?
disableHardwareMirroring()
return
}
// allocate space for list of displays
// tried to use ContiguousArray, but CGGetActiveDisplayList requires Array<CGDirectDisplayID> parameter
// ContiguousArrays cannot be typecast to Arrays (at least not easily)
var displayIDList = Array<CGDirectDisplayID>(repeating: kCGNullDirectDisplay, count: Int(displayCount))
// fill the list
postError(CGGetActiveDisplayList(displayCount, &(displayIDList), &activeCount))
// determine if mirroring is active (only relevant for software mirroring)
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master)
}
}
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
if (false) { // change to true to run the code, false to edit
toggleMirroring()
}