Mercurial Hosting > luan
view core/src/luan/modules/RpcLuan.java @ 628:6510de302f95
add "which" command
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 18 Jan 2016 06:42:50 -0700 |
parents | b4f3dbe1c6e3 |
children | cdc70de628b5 |
line wrap: on
line source
package luan.modules; import java.io.InputStream; import java.io.OutputStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.EOFException; import java.nio.charset.StandardCharsets; import java.util.Set; import java.util.IdentityHashMap; import java.util.Collections; import java.util.Map; import luan.Luan; import luan.LuanState; import luan.LuanTable; import luan.LuanFunction; import luan.LuanException; import luan.LuanMethod; public final class RpcLuan { private static final int NIL = 0; private static final int STRING = 1; private static final int BOOLEAN = 2; private static final int NUMBER = 3; private static final int BINARY = 4; private static final int TABLE = 5; @LuanMethod public static Object[] call(LuanState luan,LuanTable socketTbl,String fnName,Object... args) throws LuanException, IOException { IoLuan.LuanSocket socket = (IoLuan.LuanSocket)socketTbl.rawGet("java"); InputStream in = new BufferedInputStream(socket.inputStream()); OutputStream out = new BufferedOutputStream(socket.outputStream()); try { writeString(out,fnName); writeInt(out,args.length); for( Object arg : args ) { writeObj(out,luan,arg); } out.flush(); boolean ok = readBoolean(in); if( ok ) { int n = readInt(in); Object[] rtn = new Object[n]; for( int i=0; i<n; i++ ) { rtn[i] = readObj(in,luan); } return rtn; } else { String msg = readString(in); throw new LuanException(luan,msg); } } finally { out.close(); in.close(); } } public static void respond(LuanState luan,LuanTable socketTbl,LuanTable fns) throws IOException, LuanException { IoLuan.LuanSocket socket = (IoLuan.LuanSocket)socketTbl.rawGet("java"); InputStream in = new BufferedInputStream(socket.inputStream()); OutputStream out = new BufferedOutputStream(socket.outputStream()); try { Object[] rtn; try { String fnName = readString(in); int nArgs = readInt(in); Object[] args = new Object[nArgs]; for( int i=0; i<nArgs; i++ ) { args[i] = readObj(in,luan); } LuanFunction fn = (LuanFunction)fns.rawGet(fnName); if( fn == null ) throw new LuanException(luan, "function not found: " + fnName ); rtn = Luan.array(fn.call(luan,args)); } catch(LuanException e) { writeBoolean(out,false); writeString(out,e.getFullMessage()); return; } writeBoolean(out,true); writeInt(out,rtn.length); for( Object obj : rtn ) { writeObj(out,luan,obj); } } finally { out.close(); in.close(); } } static void writeObj(OutputStream out,LuanState luan,Object obj) throws IOException, LuanException { if( obj == null ) { out.write(NIL); } else if( obj instanceof String ) { out.write(STRING); writeString(out,(String)obj); } else if( obj instanceof Boolean ) { out.write(BOOLEAN); writeBoolean(out,(Boolean)obj); } else if( obj instanceof Number ) { out.write(NUMBER); writeString(out,obj.toString()); } else if( obj instanceof byte[] ) { byte[] a = (byte[])obj; out.write(BINARY); writeInt(out,a.length); out.write(a); } else if( obj instanceof LuanTable ) { out.write(TABLE); String s = pickle( luan, obj, Collections.newSetFromMap(new IdentityHashMap<LuanTable,Boolean>()) ); writeString(out,s); } else throw new LuanException(luan, "invalid type: " + obj.getClass() ); } static Object readObj(InputStream in,LuanState luan) throws IOException, LuanException { int type = in.read(); switch(type) { case NIL: return null; case STRING: return readString(in); case BOOLEAN: return readBoolean(in); case NUMBER: return Double.valueOf(readString(in)); case BINARY: return readBinary(in,readInt(in)); case TABLE: String s = readString(in); LuanFunction fn = BasicLuan.load(luan,s,"rpc-reader",null,true); return fn.call(luan); default: throw new LuanException(luan, "invalid type: " + type ); } } static Boolean readBoolean(InputStream in) throws IOException { return Boolean.valueOf(readString(in)); } static String readString(InputStream in) throws IOException { int len = readInt(in); byte[] a = readBinary(in,len); return new String(a,StandardCharsets.UTF_8); } static int readInt(InputStream in) throws IOException { int ch1 = in.read(); int ch2 = in.read(); int ch3 = in.read(); int ch4 = in.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } static byte[] readBinary(InputStream in,int size) throws IOException { byte[] a = new byte[size]; int i = 0; while( i < size ) { int n = in.read(a,i,size-i); if( n == -1 ) throw new EOFException(); i += n; } return a; } static void writeBoolean(OutputStream out,Boolean b) throws IOException { writeString(out,b.toString()); } static void writeString(OutputStream out,String s) throws IOException { byte[] a = s.getBytes(StandardCharsets.UTF_8); writeInt(out,a.length); out.write(a); } static void writeInt(OutputStream out,int v) throws IOException { out.write((v >>> 24) & 0xFF); out.write((v >>> 16) & 0xFF); out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); } private static String pickle(LuanState luan,Object obj,Set<LuanTable> set) throws LuanException { if( obj == null ) return "nil"; if( obj instanceof Boolean ) return obj.toString(); if( obj instanceof Number ) return Luan.toString((Number)obj); if( obj instanceof String ) return "\"" + Luan.stringEncode((String)obj) + "\""; if( obj instanceof LuanTable ) { LuanTable tbl = (LuanTable)obj; if( !set.add(tbl) ) { throw new LuanException(luan, "circular reference in table" ); } StringBuilder sb = new StringBuilder(); sb.append( "{" ); for( Map.Entry<Object,Object> entry : tbl.iterable(luan) ) { sb.append( "[" ); sb.append( pickle(luan,entry.getKey(),set) ); sb.append( "]=" ); sb.append( pickle(luan,entry.getValue(),set) ); sb.append( ", " ); } sb.append( "}" ); return sb.toString(); } throw new LuanException(luan, "invalid type: " + obj.getClass() ); } }