// Java class go.structs.Structs is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package go.structs;

import go.Seq;

public abstract class Structs {
    private Structs() {} // uninstantiable
    
    public static S Identity(S s) {
        go.Seq _in = new go.Seq();
        go.Seq _out = new go.Seq();
        S _result;
        _in.writeRef(s.ref());
        Seq.send(DESCRIPTOR, CALL_Identity, _in, _out);
        _result = new S(_out.readRef());
        return _result;
    }
    
    public static S IdentityWithError(S s) throws Exception {
        go.Seq _in = new go.Seq();
        go.Seq _out = new go.Seq();
        S _result;
        _in.writeRef(s.ref());
        Seq.send(DESCRIPTOR, CALL_IdentityWithError, _in, _out);
        _result = new S(_out.readRef());
        String _err = _out.readString();
        if (_err != null) {
            throw new Exception(_err);
        }
        return _result;
    }
    
    public static final class S implements go.Seq.Object {
        private static final String DESCRIPTOR = "go.structs.S";
        private static final int FIELD_X_GET = 0x00f;
        private static final int FIELD_X_SET = 0x01f;
        private static final int FIELD_Y_GET = 0x10f;
        private static final int FIELD_Y_SET = 0x11f;
        private static final int CALL_Identity = 0x00c;
        private static final int CALL_Sum = 0x10c;
        
        private go.Seq.Ref ref;
        
        private S(go.Seq.Ref ref) { this.ref = ref; }
        
        public go.Seq.Ref ref() { return ref; }
        
        public void call(int code, go.Seq in, go.Seq out) {
            throw new RuntimeException("internal error: cycle: cannot call concrete proxy");
        }
        
        public double getX() {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            Seq.send(DESCRIPTOR, FIELD_X_GET, in, out);
            return out.readFloat64();
        }
        
        public void setX(double v) {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            in.writeFloat64(v);
            Seq.send(DESCRIPTOR, FIELD_X_SET, in, out);
        }
        
        public double getY() {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            Seq.send(DESCRIPTOR, FIELD_Y_GET, in, out);
            return out.readFloat64();
        }
        
        public void setY(double v) {
            Seq in = new Seq();
            Seq out = new Seq();
            in.writeRef(ref);
            in.writeFloat64(v);
            Seq.send(DESCRIPTOR, FIELD_Y_SET, in, out);
        }
        
        public S Identity() throws Exception {
            go.Seq _in = new go.Seq();
            go.Seq _out = new go.Seq();
            S _result;
            _in.writeRef(ref);
            Seq.send(DESCRIPTOR, CALL_Identity, _in, _out);
            _result = new S(_out.readRef());
            String _err = _out.readString();
            if (_err != null) {
                throw new Exception(_err);
            }
            return _result;
        }
        
        public double Sum() {
            go.Seq _in = new go.Seq();
            go.Seq _out = new go.Seq();
            double _result;
            _in.writeRef(ref);
            Seq.send(DESCRIPTOR, CALL_Sum, _in, _out);
            _result = _out.readFloat64();
            return _result;
        }
        
        @Override public boolean equals(Object o) {
            if (o == null || !(o instanceof S)) {
                return false;
            }
            S that = (S)o;
            double thisX = getX();
            double thatX = that.getX();
            if (thisX != thatX) {
                return false;
            }
            double thisY = getY();
            double thatY = that.getY();
            if (thisY != thatY) {
                return false;
            }
            return true;
        }
        
        @Override public int hashCode() {
            return java.util.Arrays.hashCode(new Object[] {getX(), getY()});
        }
        
        @Override public String toString() {
            StringBuilder b = new StringBuilder();
            b.append("S").append("{");
            b.append("X:").append(getX()).append(",");
            b.append("Y:").append(getY()).append(",");
            return b.append("}").toString();
        }
        
    }
    
    private static final int CALL_Identity = 1;
    private static final int CALL_IdentityWithError = 2;
    private static final String DESCRIPTOR = "structs";
}
