精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Rust 寫腳手架,Clap你應該知道的二三事

開發(fā) 前端
和前端開發(fā)類似,當我們把包下載到本地后,我們就需要在對應的入口文件中引入并執(zhí)行。在前端開發(fā)中我們一般挑選的是項目根目錄下的index.js。而對于Rust項目來講,它的入口文件是src/main.rs。

有感而發(fā)

最近,在和前端小伙伴聊天發(fā)現(xiàn),在2024年,她們都有打算入局Rust學習的行列。畢竟前端現(xiàn)在太卷了,框架算是走到「窮途末路」了,無非就是在原有基礎上修修補補。所有他們想在新的賽道彎道超車。但是,苦于各種原因,遲遲找不到入門之法。

確實如她們所言,Rust由于學習路徑比較陡峭,加之和前端語言可以說是交集很少。然后,給大家一種學了馬上就會忘記的感覺。并且,由于現(xiàn)在Rust在前端領域的應用少之又少。除了字節(jié)跳動的Rspack,還有Vivo的Vivo Blue OS(我們在國貨之光?用Rust編寫的Vivo Blue OS有過介紹),就很少聽說其他國內互聯(lián)網公司有相關的產品和應用。

相比國外,我們的道路還任重而道遠。像國外很多耳熟能詳?shù)墓径荚缫巡季諶ust開發(fā)。最明顯的就是PhotoShop,它已經將只能在桌面運行的PS搬入了瀏覽器上。(這個我們也在之前的師夷長技以制夷:跟著PS學前端技術中有過相關介紹)

不過,從最新的招聘網站中搜索Rust相關崗位,相比前幾年有了很好的改觀。并且很多崗位都和前端相關。這說明,Rust在國內已經有了自己的市場,也意味著在前端領域也有了一席之地。那么作為職業(yè)前端,不想在紅海中繼續(xù)卷,那勢必就需要選擇藍海,方可在千軍萬馬之中,殺出一條光明之路。

其實,像我在學習Rust也遇到很她們一樣的困境。知識點看了,也理解了。但是隔斷時間就會忘記。周而復始,就會對這門語言產生一種抗拒感。畢竟,編程也算是一種技術工種,唯手熟爾。

后面,我就轉變思路,那就是動手做一些自己認為可以解決前端痛點的事。哪怕做這個事情,其他語言也可以勝任,但是為什么我們不做更進一步的嘗試呢。現(xiàn)階段,Rust在前端賦能的場景,大部分都是提高編譯效率方向。像Rspack[1]/OXC[2]。

既然,大方向已經定了,然后就有了我們新的嘗試。從那開始,就有了我們下面的嘗試方向

  1. Rust 開發(fā)命令行工具(上)
  2. Rust 開發(fā)命令行工具(中)
  3. Rust 編譯為 WebAssembly 在前端項目中使用
  4. Game = Rust + WebAssembly + 瀏覽器
  5. Rust 賦能前端-開發(fā)一款屬于你的前端腳手架

就是基于上面的不斷試錯和嘗試,到現(xiàn)在我們已經有了像f_cli[3]的npm包,并且已經部署到公司私庫,并投入生產開發(fā)了。

同時,在最近的項目開發(fā)中,還利用Rust編寫WebAssembly進行前端功能的處理。這塊等有機會寫一篇相關的文章。

前言

耽誤了大家?guī)追昼姷臅r間,在上面絮叨了半天,其實就是想傳達一個思想。Rust其實不可怕,可怕的是學了但是你沒用到工作中。就是想著法都要讓它貼切工作,應用于工作。

我們回到正題,其實Rust賦能前端這個方向我也在摸索,然后現(xiàn)階段自我感覺能用到前端項目中的無非就兩點

  1. 寫一個腳手架,將一些繁瑣操作工具化
  2. 寫wasm模塊,嵌入到前端邏輯中

大家不管是從哪個方面獲取Rust知識點,想必大家嘗試的第一個Rust應用就是Cli了。

那我們今天就來聊聊在Rust開發(fā)Cli時的神器 -clap[4]。

今天,我們只要是講相關的概念,針對如何用Rust構建一個CLI,可以翻看我們之前的文章。

好了,天不早了,干點正事哇。

我們能所學到的知識點

  1. 項目初始化
  2. 編寫子命令
  3. 添加命令標志
  4. 交互式cli
  5. 其他有用的庫

1. 項目初始化

首先,讓我們通過運行以下命令來初始化我們的項目:cargo init clap_demo。隨后我們再配置一下項目的基礎信息。(description等)

[package]
name = "clap_demo"
version = "0.1.0"
edition = "2021"
description = "front789帶你學習clap"

我們可以通過運行以下命令將 clap 添加到我們的程序中:

cargo add clap -F derive

這樣在Cargo.toml中的[dependencies]中就有了相關的信息。

[dependencies]
clap = { version = "4.5.1", features = ["derive"] }

其中-F表示,我們只需要clap中的derive特性。

圖片圖片

上述流程中,我們使用的clap的版本是最新版,有些和大家用過的語法有區(qū)別的話,需要大家甄別。

這里多說一嘴,如果對前端開發(fā)熟悉的同學是不是感覺到上述流程很熟悉。當我們創(chuàng)建一個前端項目時,是不是會遇到下面的步驟。

npm init 
yarn add xx

項目實現(xiàn)

和前端開發(fā)類似,當我們把包下載到本地后,我們就需要在對應的入口文件中引入并執(zhí)行。在前端開發(fā)中我們一般挑選的是項目根目錄下的index.js。而對于Rust項目來講,它的入口文件是src/main.rs。(作為二進制項目(Binary Projects)而言)

use clap::Parser;

#[derive(Parser)]
#[command(version, about)]
struct Cli {
    name: String
}

fn main() {
    let cli = Cli::parse();
  
    println!("Hello, {}!", cli.name);
}

我們來簡單解釋一下上面的代碼。

在前端開發(fā)中我們一般使用import/require進行第三方庫的引入,而在Rust中我們使用use來導入第三方庫clap中的Parser trait。也就是說,通過use xx我們就可以使用clap中的特定功能。也就是把對應的功能引入到該作用域內。

定義了一個結構體,它使用 clap::Parser 的 derive 宏和command宏,并且只接受一個參數(shù),即 name。

#[derive(Parser)]/#[command(version, about)]不是Rust內置的宏,它們是由clap庫自定義的過程宏(procedural macros)。

Rust有兩種類型的宏:

  1. 聲明式宏(Declarative Macros):

這些是Rust內置的,使用macro_rules定義,例如vec!、println!等。

它們主要用于元編程(metaprogramming),在編譯期執(zhí)行代碼生成。

  1. 過程宏(Procedural Macros):
  • 這些是由外部crate定義的,在編譯期間像函數(shù)一樣被調用。
  • 它們可以用來實現(xiàn)自定義的代碼生成、lint檢查、trait派生,解析、操作和生成 AST等操作。

#[derive(Parser)]它使用 derive 屬性來自動為 Cli 結構體實現(xiàn) Parser trait。這意味著 Cli 結構體將獲得解析命令行參數(shù)的功能,而無需手動實現(xiàn) Parser trait。

圖片圖片

#[command(version, about)]用于配置命令行應用程序的元數(shù)據。

  • version: 設置應用程序的版本信息。
  • about: 設置應用程序的簡短描述。這里的信息就是我們在Cargo.toml中配置的description的信息。

最后,我們可以通過cargo run -- --help來查看對應的信息。

圖片圖片

總的來說,這段代碼使用 clap 庫定義了一個命令行應用程序,它接受一個名為 name 的字符串參數(shù)。當運行這個應用程序時,它會打印出 "Hello, {name}"。#[derive(Parser)] 和 #[command(...)] 這兩個屬性分別用于自動實現(xiàn) Parser trait 和配置應用程序的元數(shù)據。

當我們加載程序并使用 Cli::parse() 時,它將從 std::env::args 中獲取參數(shù)(這個概念我們之前在環(huán)境變量:熟悉的陌生人有過介紹)。

  • 如果你嘗試運行 cargo run front789,它應該會打印出 Hello, front789!
  • 但如果嘗試不添加任何額外值運行它,它將打印出幫助菜單。Clap 在默認特性中包含了一個幫助功能,當輸入的命令無效時會自動顯示幫助菜單。

當然,如果想讓我們的程序更加健壯,我們可以給name設定一個默認值,這樣在沒有提供參數(shù)的情況下,也能合理運行。

#[derive(Parser,Debug)]
#[command(version, about)]
struct Cli {
    #[arg(default_value = "front789")]
    name: String
}

現(xiàn)在,嘗試僅使用 cargo run 而不添加其他任何東西,它應該會打印出 Hello, front789!。

圖片圖片

當然,我們也可以像在f_cli中一樣為參數(shù)添加更多的配置,來增強我們的Cli。

圖片圖片

如果想了解更多關于參數(shù)配置,可以翻看clap_command-attributes[5]

圖片圖片

2. 編寫子命令

作為一個功能強大的CLI,我們有時候需要通過定義一些子命令來讓我們的目的更加明確。

如果大家用過我們的f_cli,那就心領神會了。

下圖是我們f_cli的根據用戶提供的參數(shù),默認構建前端項目的命令。

圖片圖片

在f_cli的實現(xiàn)中,我們就用到了子命令的操作。

圖片圖片

下面我們來簡單實現(xiàn)一個擁有子命令的cli。在之前代碼的基礎上,我們只需要將剛才結構體中再新增一個參數(shù) - command并且其類型為實現(xiàn)sumcommad trait的枚舉

use clap::{ Parser, Subcommand };

#[derive(Parser,Debug)]
#[command(version, about)]
struct Cli {
    #[arg(default_value = "front789")]
    name: String,
    #[command(subcommand)]
    command: Commands
}

#[derive(Subcommand, Debug, Clone)]
enum Commands {
    Create,
    Replace,
    Update,
    Delete
}

fn main() {
    let cli = Cli::parse();
  
    println!("Hello, {:?}!", cli);
}

這樣,我們就在上面的基礎上擁有了一組子命令(CRUD)。這樣我們就可以在cli中調用對應的子命令然后執(zhí)行對應的操作了。

圖片圖片

3. 添加命令標志

我們可以繼續(xù)豐富我們子命令。上面的我們不是通過一個枚舉Commands夠了一個組件命令(Create/Replace/Update/Delete)嗎。

有時候,在某一個子命令下,還需要收集更多的用戶選擇。那么我們就可以將枚舉中的值關聯(lián)成一個「匿名結構體」。這樣,我們就可以針對某個子命令做更深的操作了。

還是舉我們之前的f_cli的例子,在我們通過f_cli create xxx構建項目時,我們可以通過-x來像CLI傳遞Create所用到的必要信息。

圖片圖片

use clap::{ Parser, Subcommand };

#[derive(Parser,Debug)]
#[command(version, about)]
struct Cli {
    #[arg(default_value = "front789")]
    name: String,
    #[command(subcommand)]
    command: Commands
}

#[derive(Subcommand, Debug, Clone)]
enum Commands {
    Create{
         #[arg(default_value = "front789")]
        name: String,
         #[arg(default_value = "山西")]
        address: String,
    },
    Replace,
    Update,
    Delete
}

這樣我們就對Create進一步處理,并且在create的時候,它會從命令行中尋找對應的name/address信息,并且收集到clap實例中。

隨后,我們就可以在主函數(shù)中通過match來匹配枚舉信息,然后執(zhí)行相對應的操作。

Rust 中的匹配是窮舉式的:必須窮舉到最后的可能性來使代碼有效

為了節(jié)約代碼量,我們通過_占位符來處理其他的邏輯。

fn main() {
    let cli = Cli::parse();
    match cli.command {
        Commands::Create{name,address} => {
            println!("我是{},來自:{}", name,address);
        },
       _=>(),
    }
}

當我們運行cargo run create時,由于我們提供了默認值,在控制臺就會輸出對應的信息。當然,我們也可以通過-- name xx -- address xx來進行操作。

有人會覺得輸入較長的子命令不是很友好,我們可以通過short = 'n'來為子命令提供一個別名。同時我們還可以通過help="xxx"設置對應在--help時,提供給用戶的幫助信息。

圖片圖片

對應的代碼如下:

#[derive(Subcommand, Debug, Clone)]
enum Commands {
    Create{
         #[arg(
            short = 'n',
            lnotallow="name",
            help = "用戶信息",
            default_value = "front789"
        )]
        name: String,
         #[arg(
            short = 'a',
            lnotallow="address",
            help = "地址信息",
            requires = "name",
            default_value = "山西"
        )]
        address: String,
    },
    Replace,
    Update,
    Delete
}

4. 交互式cli

在上一節(jié)中我們通過對CLI枚舉進行改造,讓其能夠擁有了子命令的功能。其實到這步已經能夠獲取到cli中用戶輸入的值,并且能夠進行下一步的操作了。

但是呢,你是一個精益求精的人。見多識廣的你突然有一個想法,為什么不能像vite/create/next一樣。在觸發(fā)對應的構建和更新操作后,有一個「人機交互」的過程。然后,用戶可以根據自己的喜好來選擇我們cli的內置功能。這樣是不是顯的更加友好。

像我們的f_cli就是這種交互流程。用戶通過人機交互的方式可以選擇內置功能。

圖片圖片

f_cli 選擇UI庫

那我們就再次用一個簡單的例子來介紹一下哇。

安裝新的包

首先,我們需要安裝幾個用于交互的包。

cargo add anyhow
cargo add dialoguer
cargo add console

隨后,就他們就會自動被注入到Cargo.toml中了。關于anyhow/dialoguer/console我們就不在這里過多介紹了。大家感興趣可以去對應的官網查找.

  • dialoguer[6]
  • console[7]
  • anyhow[8]

現(xiàn)在,我們需要在src/main.rs中引入相關的功能,同時我們在處理cli變量的時候,用的是枚舉值,所以我們需要引入clap中針對這類的操作。

use clap::{ 
+    builder::EnumValueParser, 
     Parser, 
     Subcommand, 
+    ValueEnum 
};

+use dialoguer::{ 
+  console::Term, 
+  theme::ColorfulTheme, 
+  Select 
+};
+use console::style;

新增枚舉信息

前面說過,我們想通過人機交互的方式,在cli運行過程中讓用戶自己選擇我們內置的功能點。所以,這些內置功能我們可以需要事先設定好。

#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
pub enum Name {
    N1,
    N2,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
pub enum Address {
    A1,
    A2
}

處理結構體中參數(shù)的默認值

既然,已經有了對應的默認值,那么我們就需要限制我們cli中的參數(shù)必須是這些內置參數(shù)中值。

#[derive(Subcommand, Debug, Clone)]
enum Commands {
    Create{
         #[arg(
            short = 'n',
            lnotallow="name",
            help = "用戶信息",
+            value_parser = EnumValueParser::<Name>::new(),
            ignore_case = true
        )]
+        name: Option<Name>,
         #[arg(
            short = 'a',
            lnotallow="address",
            help = "地址信息",
            requires = "name",
+           value_parser = EnumValueParser::<Address>::new(),
        )]
+       address: Option<Address>,
    }
}

上面的配置,見名知意,就是從對應的枚舉中解析對應的值。

主函數(shù)

其實,這步的操作和之前是差不多的,我們還是利用match對cli.command進行匹配處理。不過我們這里又進一步的做了容錯處理。

  1. 首先判斷是否提供子命令
  2. 在提供子命令的情況下,再判斷是否是Craete

因為,在進行操作中我們會有錯誤拋出,所以我們對main的返回值也做了處理。(anyhow::Result<()>)

fn main() ->anyhow::Result<()> {
    let cli = Cli::parse();
    match cli.command {
        // - 如果有子命令,則根據子命令執(zhí)行相應的邏輯;
        Some(command) => {
            match command {
                Commands::Create {
                    name,
                    address,
                } => 
                operation_params(
                  name,
                  address
                )?,
            }
        },
         _ => panic!("Fatal: cli為提供參數(shù),退出處理."),
    }
    Ok(())
}

operation_params

在main中我們通過match是可以獲取到cli中參數(shù)的,而此時我們還需要根據參數(shù)做進一步的處理。我們把這個邏輯提取到了一個函數(shù)中了。

fn operation_params (
    name: Option<Name>,
    address: Option<Address>
) -> anyhow::Result<()> {
     let n = match name {
        Some(na) => na,
        None => {
            multiselect_msg("選擇一個姓名:");
            message("使用上/下箭頭進行選擇,使用空格或回車鍵確認。");
            let items = vec!["張三", "王五"];
            let selection = Select::with_theme(&ColorfulTheme::default())
                .items(&items)
                .default(0)
                .interact_on_opt(&Term::stderr())?;

            match selection {
                Some(0) => Name::N1,
                Some(1) => Name::N2,
                _ => panic!("Fatal: 用戶信息制定錯誤."),
            }
        }
    };
     let a = match address {
        Some(na) => na,
        None => {
            multiselect_msg("選擇一個地址:");
            message("使用上/下箭頭進行選擇,使用空格或回車鍵確認。");
            let items = vec!["太原", "晉中"];
            let selection = Select::with_theme(&ColorfulTheme::default())
                .items(&items)
                .default(0)
                .interact_on_opt(&Term::stderr())?;

            match selection {
                Some(0) => Address::A1,
                Some(1) => Address::A2,
                _ => panic!("Fatal: 地址信息制定錯誤."),
            }
        }
    };
    println!("name:{:?},地址:{:?}",n,a);
   Ok(())
}

其實上面的邏輯也是比較簡單明了的。 我們接收cli中的參數(shù)name/address。因為他們都是枚舉類型,所以我們繼續(xù)用match進行對應值的匹配。

雖然,我們對兩個枚舉值都做了處理,但是他們的邏輯都是相同的。

上面的邏輯就是當我們運行子命令時候

  • 當提供對應的參數(shù)的話,那就原封不動的返回對應的值
  • 當沒有提供對應的參數(shù)的話,我們就調用dialoguer::Select進行我們預設值的選擇。

圖片圖片

這樣,不管我們上面那種情況,我們最后都可以拿到對應的值。這樣我們方便我們后期進行其他操作。

5. 其他有用的庫

上面我們通過幾個例子,講了很多clap的應用例子,其中我們還配合dialoguer進行人機交互的處理。如果我們想實現(xiàn)功能更加強大的cli我們還可以借助其他的工具。下面我們就來簡單介紹幾種。

Crossterm

crossterm[9] 是一款跨終端的crate。 它具有各種很酷的功能,如能夠更改背景和文本顏色、操作終端本身和光標,以及捕獲鍵盤和其他事件。

圖片圖片

comfy-table

comfy-table[10] 是一個設計用于在終端中創(chuàng)建漂亮表格的 crate。

以下是其官網的案例。用僅僅幾句話就可以實現(xiàn)一個在終端展示的表格。

use comfy_table::Table;

fn main() {
    let mut table = Table::new();
    table
        .set_header(vec!["Header1", "Header2", "Header3"])
        .add_row(vec![
            "This is a text",
            "This is another text",
            "This is the third text",
        ])
        .add_row(vec![
            "This is another text",
            "Now\nadd some\nmulti line stuff",
            "This is awesome",
        ]);

    println!("{table}");
}

執(zhí)行后的效果如下:

+----------------------+----------------------+------------------------+
| Header1              | Header2              | Header3                |
+======================================================================+
| This is a text       | This is another text | This is the third text |
|----------------------+----------------------+------------------------|
| This is another text | Now                  | This is awesome        |
|                      | add some             |                        |
|                      | multi line stuff     |                        |
+----------------------+----------------------+------------------------+

inquire

inquire[11] 是一個用于構建終端上交互式提示的 crate。它支持單選、多選、選擇日歷等功能:

下面的動圖是其官網的案例。其中最吸引我的就是那個多選。哈哈。

圖片圖片


責任編輯:武曉燕 來源: 前端柒八九
相關推薦

2021-01-07 05:34:07

腳手架JDK緩存

2022-07-18 07:58:46

Spring工具工具類

2010-08-09 13:20:36

Flex

2015-11-05 18:03:15

虛擬化云計算資源池

2017-11-03 13:43:24

云計算Saas信息化

2022-03-11 07:47:56

防御性編程互聯(lián)網

2016-09-07 15:35:06

VueReact腳手架

2025-05-16 07:24:41

Springkafka腳手架

2021-12-23 10:35:32

SpringCloud腳手架架構

2015-10-26 09:19:28

PHP經驗

2020-03-20 08:32:41

物聯(lián)網腳手架傳感器

2021-05-21 05:22:52

腳手架工具項目

2018-05-30 12:04:36

LinuxUbuntu 18.0

2017-10-24 09:39:03

2011-08-22 22:27:22

2018-08-30 16:08:37

Node.js腳手架工具

2022-04-24 11:33:47

代碼管理工程

2019-12-25 15:20:48

前端腳手架命令

2018-06-11 14:39:57

前端腳手架工具node.js

2023-11-21 17:36:04

OpenFeignSentinel
點贊
收藏

51CTO技術棧公眾號

www国产精品视频| 欧美日韩情趣电影| 日韩免费电影一区二区| 怡红院男人天堂| 欧美视频网站| 亚洲日韩第一页| 国产成人av免费观看| 欧产日产国产精品视频| 一区在线观看免费| 乱色588欧美| av网站免费大全| 欧美资源在线| 欧美久久精品午夜青青大伊人| 国产原创剧情av| 日韩欧美专区| 日韩欧亚中文在线| www.日本在线视频| 美女国产在线| 国产亚洲一区字幕| 超碰97在线资源| 亚洲视频在线观看一区二区| 亚洲国内精品| 欧美大奶子在线| 国产免费嫩草影院| 四虎影视精品| 亚洲成人精品在线| 99精品999| 日韩精品免费观看视频| 午夜国产不卡在线观看视频| 亚洲日本精品| 国产精品视频二区三区| 99久久久国产精品免费蜜臀| 亚洲在线观看视频| 97在线视频人妻无码| 日韩精品乱码av一区二区| 97国产精品人人爽人人做| 欧美黑人一级片| 欧美成人嫩草网站| 久久视频在线直播| 国产麻豆视频在线观看| 成人看的羞羞网站| 亚洲网站视频福利| 波多野结衣av在线观看| 日韩av不卡一区| 日韩成人在线免费观看| 欧美激情 亚洲| 黄色免费大全亚洲| 亚洲高清福利视频| 日本在线不卡一区二区| 国产精品chinese在线观看| 日韩欧美国产三级电影视频| 成人在线短视频| 日韩成人在线观看视频| 日韩精品一区二区三区视频 | 免费欧美电影| 在线观看亚洲专区| 三级a在线观看| 99久久婷婷国产综合精品首页 | 中文字幕成人av| 日韩欧美一区二区三区四区五区| 久草在线免费福利资源| 久久精品视频在线看| 日韩欧美视频一区二区三区四区| 一级毛片视频在线| 亚洲欧美日韩精品久久久久| 黄色一级视频播放| 波多野结衣精品| 欧美小视频在线| 乌克兰美女av| 日韩高清一区| 亚洲欧美国产精品va在线观看| 中文字幕免费高清| 91久久高清国语自产拍| 欧美国产精品人人做人人爱| 日韩欧美中文字幕一区二区| 久久精品官网| 成人欧美在线视频| 欧美特黄一级视频| 国产日韩欧美精品综合| 四虎免费在线观看视频| 182在线视频观看| 色哟哟在线观看一区二区三区| 少妇一级淫免费放| 亚洲一区二区三区四区电影| 精品爽片免费看久久| 91成人精品一区二区| 欧美精品国产一区二区| 欧美一级片久久久久久久| 中文字幕一区二区三区人妻四季 | 国产一区二区三区无遮挡| 日本黄在线观看| 中文字幕日韩一区二区| 亚洲 欧美 日韩 国产综合 在线| 日韩在线短视频| 欧美大片在线观看| 国产传媒国产传媒| 欧美午夜不卡| 国产精品免费久久久| www.国产欧美| 欧美国产禁国产网站cc| 欧美乱大交xxxxx潮喷l头像| 制服诱惑亚洲| 亚洲国产日韩一区| 日日噜噜夜夜狠狠久久波多野| 在线亚洲成人| 99一区二区三区| 中国日本在线视频中文字幕| 亚洲高清三级视频| 国内av一区二区| 欧美影院三区| 欧美亚洲另类视频| 午夜精品久久久久久久99老熟妇| 久久精品视频网| 欧美成人高潮一二区在线看| 成人国产精品一区二区网站| 亚洲欧美在线一区| 日本五十熟hd丰满| 国产一区二区三区精品视频| 欧美日韩三区四区| 国产精品一区二区日韩| 日韩视频一区二区三区| 久久久久99精品成人| 亚洲欧美日韩专区| 精品无人区一区二区三区竹菊| 亚洲小说区图片区都市| 欧美群妇大交群中文字幕| 麻豆国产精品一区| 精品动漫av| 成人蜜桃视频| 2024最新电影免费在线观看| 精品视频1区2区| 亚洲天堂岛国片| 久久久久久黄| 久久99九九| 色一区二区三区| 亚洲精品久久久久| 天堂网av手机版| 成人福利视频网站| 日本人妻伦在线中文字幕| 榴莲视频成人app| 久久国产精品久久久久久久久久| 在线播放一级片| 国产精品人人做人人爽人人添| av视屏在线播放| 国内成人自拍| 国产精品视频xxx| 888av在线| 欧美日韩精品高清| 97精品在线播放| 国内精品视频一区二区三区八戒| 在线免费观看成人网| 成人污污视频| 色综合91久久精品中文字幕| 亚洲国产精品suv| 亚洲成人午夜影院| 免费的av网站| 免费看亚洲片| 亚洲人成网站在线播放2019| 亚洲高清影院| 欧美裸体男粗大视频在线观看 | 日韩毛片中文字幕| 在线精品免费视| 国产精品区一区二区三区| 国产5g成人5g天天爽| 中文字幕免费精品| 国产伦精品一区二区三区四区免费 | 99久久精品免费看国产交换| 一区二区三区不卡在线观看| fc2成人免费视频| 免费在线亚洲欧美| 亚洲精品国产一区| 欧美日本三级| 欧洲一区二区视频| 成人黄视频在线观看| 欧美成人精品3d动漫h| 97超碰人人干| 国产精品美女久久久久久久久 | 欧美人交a欧美精品| 天天爽夜夜爽夜夜爽| 在线欧美小视频| 成人自拍小视频| 99久久精品国产网站| 国产精品69页| 午夜亚洲福利| 日本中文不卡| 91蝌蚪精品视频| 国产成人综合久久| 最新日本在线观看| 亚洲欧美另类自拍| www.四虎在线观看| 日本高清免费不卡视频| 一区二区视频免费看| 91麻豆123| 丰满人妻一区二区三区大胸 | 亚洲国产精品影院| 丁香激情五月少妇| 成人小视频免费在线观看| 亚洲免费一级视频| 国产日韩欧美三级| 在线播放 亚洲| 久久av网址| 国产传媒一区二区| 成人精品国产亚洲| 7777精品视频| 黑人另类精品××××性爽| 中文字幕少妇一区二区三区| 日本激情一区二区三区| 制服.丝袜.亚洲.中文.综合| 高潮毛片又色又爽免费| 夜夜揉揉日日人人青青一国产精品 | 久久99国产精品自在自在app | 精品中文字幕在线| 尤物视频在线免费观看| 亚洲视频欧美视频| 天堂中文在线官网| 日韩欧美激情四射| 91亚洲视频在线观看| 色视频成人在线观看免| 日韩精品一区二区av| 亚洲日韩欧美一区二区在线| 欧美熟妇激情一区二区三区| 99re6这里只有精品视频在线观看| 日韩欧美中文在线视频| 精品系列免费在线观看| 韩国中文字幕av| 母乳一区在线观看| 欧美日韩一道本| 最新日韩av| 欧美国产日韩激情| 最新成人av网站| 黄色成人在线看| 亚洲日韩成人| www.欧美黄色| 欧美午夜久久| 欧美久久久久久久久久久久久久| 欧美ab在线视频| 大片在线观看网站免费收看| 亚洲二区三区不卡| 制服国产精品| 亚洲一本二本| www.亚洲一区二区| 欧美伊人影院| av动漫在线免费观看| 国产精品vip| 一本久道高清无码视频| 99视频精品| 国产一区二区三区精彩视频| 亚久久调教视频| 中文久久久久久| 麻豆国产欧美日韩综合精品二区| 色悠悠久久综合网| 国产综合色产在线精品| 少妇欧美激情一区二区三区| 成人午夜在线播放| 色天使在线视频| 国产日韩在线不卡| 91制片厂在线| 一个色在线综合| 国产微拍精品一区| 在线免费观看日本一区| 一区二区视频免费观看| 日韩一区二区三| 欧洲精品久久一区二区| 亚洲男人7777| 免费超碰在线| 欧美日本黄视频| 中文字幕21页在线看| 国产成人一区二区三区| 亚洲在线资源| 国产在线播放一区二区| 国产一区二区在线| dy888午夜| 一道本一区二区| 蜜桃免费在线视频| 国产成人av电影在线| 亚洲专区区免费| 国产精品国产a级| 日韩精品一区三区| 色菇凉天天综合网| 国产三区在线播放| 日韩精品黄色网| 四虎久久免费| 97欧美精品一区二区三区| 电影亚洲精品噜噜在线观看| 91精品啪在线观看麻豆免费| 国产精品115| 一区二区三区欧美在线| 亚洲免费精品| 亚洲精品免费一区亚洲精品免费精品一区| 国产91综合一区在线观看| 久久亚洲无码视频| 亚洲综合一区二区三区| 日韩欧美国产另类| 精品国产一区二区三区四区四| 都市激情在线视频| 久久久久久这里只有精品| 嫩草伊人久久精品少妇av杨幂| 国产成人精品一区二区三区福利| 日韩片欧美片| 欧美性大战久久久久xxx | 午夜亚洲激情| 中文字幕无码毛片免费看| 久久久不卡影院| 国产亚洲自拍av| 在线不卡免费欧美| 巨骚激情综合| 91wwwcom在线观看| 日本一区二区三区视频在线看 | 区一区二区三区中文字幕| 国内精品久久久久久久影视麻豆| 丰满少妇在线观看| 99re6这里只有精品视频在线观看| 粉嫩av性色av蜜臀av网站| 欧美综合亚洲图片综合区| 亚洲人午夜射精精品日韩| 久久99国产精品久久久久久久久| 成人精品三级| 日韩精品一区二区三区外面| 99热精品在线| 97香蕉碰碰人妻国产欧美 | 美女主播精品视频一二三四| 好色先生视频污| 韩国女主播成人在线| www.99热| 欧美色图免费看| 成人免费一区二区三区视频网站| 97av在线视频免费播放| 91在线一区| 日韩欧美精品免费| 国产成人亚洲综合色影视| 91精品一区二区三区蜜桃| 欧美日韩你懂的| eeuss影院在线观看| 国产精品福利久久久| 久草成人在线| 无码少妇一区二区三区芒果| 国产亚洲精品aa午夜观看| 亚洲天堂av片| 国产性色av一区二区| 97久久网站| 亚洲欧美日韩在线综合| 久久国产麻豆精品| 国产大屁股喷水视频在线观看| 精品视频1区2区| 搞黄网站在线观看| 7777精品伊久久久大香线蕉语言 | 亚洲图片欧美色图| 色呦呦中文字幕| 26uuu日韩精品一区二区| 日韩欧美美女在线观看| 黄色动漫在线免费看| 久久午夜色播影院免费高清 | 美女福利一区二区| 欧美一级爽aaaaa大片| 蜜臀久久久99精品久久久久久| 国产无遮挡在线观看| 欧美精品 国产精品| 肉体视频在线| 久久爱av电影| 蜜臀久久99精品久久久久久9| 国产三级精品三级观看| 日韩一级欧美一级| 欧美极品videos大乳护士| 免费在线一区二区| 久久成人免费日本黄色| 欧美日韩在线视频免费| 亚洲精品久久在线| 春暖花开亚洲一区二区三区| 一区二区精品国产| 国产99久久精品| 成人公开免费视频| www.亚洲一区| 日本国产精品| 不用播放器的免费av| 亚洲成在人线在线播放| 男同在线观看| 92裸体在线视频网站| 国产日韩1区| 久久嫩草捆绑紧缚| 精品国产精品一区二区夜夜嗨| 成人免费直播| 免费cad大片在线观看| 97久久人人超碰| 91久久久久国产一区二区| 欧美激情一二三| 色97色成人| 日韩av无码一区二区三区不卡| 欧美在线高清视频| 爱情岛亚洲播放路线| 亚洲一区二区在| 99精品黄色片免费大全| 96日本xxxxxⅹxxx17| 91精品国产91久久久| 99精品在线| 91成年人网站| 欧美成人一级视频| 国产精品黄色片| 无码人妻精品一区二区三区在线| 中文字幕在线视频一区| 深夜福利视频在线观看|