2014-11-17 4 views
2

У меня есть буфер Byte[], который может содержать один или несколько кадров данных. Мне нужно прочитать первые байты, чтобы узнать, сколько времени занимает фактический кадр.F # соответствует началу массива

Это «нерабочая» версия о том, что я хочу сделать:

let extractFrame (buffer:byte[]) = 
    match buffer with 
    | [|head1;head2;head3;..|] when head2 < (byte)128 -> processDataFrame buffer head2 
    | <...others....> 
    | _ -> raise(new System.Exception()) 

В принципе, мне нужно оценить первые три байта, а затем вызвать processDataFrame с буфером и фактической длиной рама. В зависимости от заголовков, кадр может быть данными, контролем и т. Д.

Можно ли это сделать с любым типом соответствия (списки, последовательности, ... и т. Д.)? Или мне нужно создать еще один небольшой массив с длиной всего заголовка? (Я бы хотел этого избежать).

+0

Не было бы проще просто оценить первые три байта с помощью if/then? –

+0

вот что я пытаюсь выяснить ... Есть много случаев, и мне было интересно, как это сделать в F # – vtortola

ответ

3

Если вы хотите использовать соответствующие вы могли бы создать активный шаблон (http://msdn.microsoft.com/en-us/library/dd233248.aspx):

let (|Head1|_|) (buffer:byte[]) = 
    if(buffer.[0] (* add condition here *)) then Some buffer.[0] 
    else None 

let (|Head2|_|) (buffer:byte[]) = 
    if(buffer.[1] < (byte)128) then Some buffer.[1] 
    else None 

let extractFrame (buffer:byte[]) = 
    match buffer with 
    | Head1 h1 -> processDataFrame buffer h1 
    | Head2 h2 -> processDataFrame buffer h2 
........ 
    | _ -> raise(new System.Exception()) 
+0

Правильно, это имеет смысл. Благодаря! – vtortola

3

Я думаю, что это могло бы быть на самом деле проще сделать, используя простую if конструкцию.

Но, как отметил Петр, вы можете использовать активные шаблоны и определять свои собственные шаблоны, которые извлекают определенную информацию из массива. Чтобы смоделировать то, что вы делаете, я бы фактически использовал параметризованный активный шаблон - вы можете указать ему количество элементов из массива, в котором вы нуждаетесь, и он дает вам массив, например. 3 элемента обратно:

let (|TakeSlice|_|) count (array:_[]) = 
    if array.Length < count then None 
    else Some(array.[0 .. count-1]) 

let extractFrame (buffer:byte[]) = 
    match buffer with 
    | TakeSlice 3 [|head1;head2;head3|] when head2 < (byte)128 -> 
     processDataFrame buffer head2 
    | <...others....> 
    | _ -> raise(new System.Exception()) 

Одним из недостатков этого подхода заключается в том, что ваш шаблон [|h1; h2; h3|] должен соответствовать длине, которую вы указали 3 - компилятор не может проверить это для вас.

+0

Я не могу каждый раз создавать новый массив, поскольку он является серверным приложением и будет создавать тысячи в секунду. – vtortola

+0

Я думаю, вы могли бы придумать что-то более умное - вроде return 'ArraySegment' :-) –

+0

Право, все еще тысячи этих объектов в секунду: DI чувствует себя более расслабленным, работая с буфером, смещением и длиной ... слишком старая школа, возможно, , – vtortola

Смежные вопросы